DVB-S PCI card regression on 4.19 / 4.20

2018-11-19 Thread Takashi Iwai
Hi,

we've got a regression report on openSUSE Bugzilla regarding DVB-S PCI
card:
  https://bugzilla.opensuse.org/show_bug.cgi?id=1116374

According to the reporter (Stakanov, Cc'ed), the card worked fine on
4.18.15, but since 4.19, it doesn't give any channels, sound nor
picture, but only EPG is received.

The following errors might be relevant:


[4.845180] b2c2-flexcop: B2C2 FlexcopII/II(b)/III digital TV receiver chip 
loaded successfully
[4.869703] b2c2-flexcop: MAC address = xx:xx:xx:xx:xx:xx
[5.100318] b2c2-flexcop: found 'ST STV0299 DVB-S' .
[5.100323] b2c2_flexcop_pci :06:06.0: DVB: registering adapter 0 
frontend 0 (ST STV0299 DVB-S)...
[5.100370] b2c2-flexcop: initialization of 'Sky2PC/SkyStar 2 DVB-S rev 2.6' 
at the 'PCI' bus controlled by a 'FlexCopIIb' complete
[  117.513086] b2c2_flexcop_pci :06:06.0: DVB: adapter 0 frontend 0 
frequency 1549000 out of range (95..2150)
[  124.905222] b2c2_flexcop_pci :06:06.0: DVB: adapter 0 frontend 0 
frequency 188 out of range (95..2150)
[  127.337079] b2c2_flexcop_pci :06:06.0: DVB: adapter 0 frontend 0 
frequency 1353500 out of range (95..2150)


The lspci shows:

06:06.0 Network controller: Techsan Electronics Co Ltd B2C2 FlexCopII DVB chip 
/ Technisat SkyStar2 DVB card (rev 02)
Subsystem: Techsan Electronics Co Ltd B2C2 FlexCopII DVB chip / 
Technisat SkyStar2 DVB card
Control: I/O+ Mem+ BusMaster+ SpecCycle- MemWINV- VGASnoop- ParErr- 
Stepping- SERR- FastB2B- DisINTx-
Status: Cap- 66MHz- UDF- FastB2B- ParErr- DEVSEL=slow >TAbort- SERR- 

Re: [RFC PATCH] sound, media: array_find() can be static

2018-04-23 Thread Takashi Iwai
On Sun, 22 Apr 2018 20:05:03 +0200,
kbuild test robot wrote:
> 
> 
> Fixes: dbd775375e7d ("sound, media: allow building ISA drivers it with 
> COMPILE_TEST")

It's not actually a bug that was introduced by the commit, but it just
made appearing clearer.  So I dropped this tag.

> Signed-off-by: Fengguang Wu 

The fix is applied now.  Thanks.


Takashi


Re: [PATCH 3/4] sound, media: allow building ISA drivers it with COMPILE_TEST

2018-04-23 Thread Takashi Iwai
On Sun, 22 Apr 2018 20:05:03 +0200,
kbuild test robot wrote:
> 
> Hi Mauro,
> 
> I love your patch! Perhaps something to improve:
> 
> [auto build test WARNING on linuxtv-media/master]
> [also build test WARNING on v4.17-rc1 next-20180420]
> [if your patch is applied to the wrong git tree, please drop us a note to 
> help improve the system]
> 
> url:
> https://github.com/0day-ci/linux/commits/Mauro-Carvalho-Chehab/media-radio-allow-building-ISA-drivers-with-COMPILE_TEST/20180422-180508
> base:   git://linuxtv.org/media_tree.git master
> reproduce:
> # apt-get install sparse
> make ARCH=x86_64 allmodconfig
> make C=1 CF=-D__CHECK_ENDIAN__
> 
> 
> sparse warnings: (new ones prefixed by >>)
> 
> >> sound/isa/wss/wss_lib.c:551:14: sparse: restricted snd_pcm_format_t 
> >> degrades to integer


Oh, so many minor issues surfaced by COMPILE_TEST.
But these are all legacy ISA drivers, so I'll work on and take only safe
fixes that are obvious and trivial, if any.


thanks,

Takashi


Re: [PATCH] sound, isapnp: allow building more drivers with COMPILE_TEST

2018-04-20 Thread Takashi Iwai
On Fri, 20 Apr 2018 14:58:55 +0200,
Mauro Carvalho Chehab wrote:
> 
> Drivers that depend on ISAPNP currently can't be built with
> COMPILE_TEST. However, looking at isapnp.h, there are already
> stubs there to allow drivers to include it even when isa
> PNP is not supported.
> 
> So, remove such dependencies when COMPILE_TEST.
> 
> Signed-off-by: Mauro Carvalho Chehab <mche...@s-opensource.com>

Acked-by: Takashi Iwai <ti...@suse.de>


thanks,

Takashi


> ---
>  drivers/pnp/isapnp/Kconfig | 2 +-
>  sound/isa/Kconfig  | 6 +++---
>  2 files changed, 4 insertions(+), 4 deletions(-)
> 
> diff --git a/drivers/pnp/isapnp/Kconfig b/drivers/pnp/isapnp/Kconfig
> index f1ef36673ad4..a1af146d2d90 100644
> --- a/drivers/pnp/isapnp/Kconfig
> +++ b/drivers/pnp/isapnp/Kconfig
> @@ -3,7 +3,7 @@
>  #
>  config ISAPNP
>   bool "ISA Plug and Play support"
> - depends on ISA
> + depends on ISA || COMPILE_TEST
>   help
> Say Y here if you would like support for ISA Plug and Play devices.
> Some information is in .
> diff --git a/sound/isa/Kconfig b/sound/isa/Kconfig
> index d2a6cdd0395c..43b35a873d78 100644
> --- a/sound/isa/Kconfig
> +++ b/sound/isa/Kconfig
> @@ -39,7 +39,7 @@ config SND_ADLIB
>  
>  config SND_AD1816A
>   tristate "Analog Devices SoundPort AD1816A"
> - depends on PNP && ISA
> + depends on PNP
>   select ISAPNP
>   select SND_OPL3_LIB
>   select SND_MPU401_UART
> @@ -67,7 +67,7 @@ config SND_AD1848
>  
>  config SND_ALS100
>   tristate "Diamond Tech. DT-019x and Avance Logic ALSxxx"
> - depends on PNP && ISA
> + depends on PNP
>   select ISAPNP
>   select SND_OPL3_LIB
>   select SND_MPU401_UART
> @@ -108,7 +108,7 @@ config SND_AZT2316
>  
>  config SND_AZT2320
>   tristate "Aztech Systems AZT2320"
> - depends on PNP && ISA
> + depends on PNP
>   select ISAPNP
>   select SND_OPL3_LIB
>   select SND_MPU401_UART
> -- 
> 2.14.3
> 
> 


Re: [PATCH 3/4] sound, media: allow building ISA drivers it with COMPILE_TEST

2018-04-20 Thread Takashi Iwai
On Fri, 20 Apr 2018 15:01:22 +0200,
Mauro Carvalho Chehab wrote:
> 
> Em Fri, 20 Apr 2018 09:51:29 -0300
> Mauro Carvalho Chehab <mche...@s-opensource.com> escreveu:
> 
> > Em Fri, 20 Apr 2018 14:37:46 +0200
> > Takashi Iwai <ti...@suse.de> escreveu:
> > 
> > > On Fri, 20 Apr 2018 14:32:15 +0200,
> > > Mauro Carvalho Chehab wrote:  
> > > > 
> > > > All sound drivers that don't depend on PNP can be safelly
> > > > build with COMPILE_TEST, as ISA provides function stubs to
> > > > be used for such purposes.
> > > > 
> > > > As a side effect, with this change, the radio-miropcm20
> > > > can now be built outside i386 with COMPILE_TEST.
> > > > 
> > > > Signed-off-by: Mauro Carvalho Chehab <mche...@s-opensource.com>
> > > > ---
> > > >  drivers/media/radio/Kconfig | 3 ++-
> > > >  sound/isa/Kconfig   | 9 +
> > > >  2 files changed, 7 insertions(+), 5 deletions(-)
> > > > 
> > > > diff --git a/drivers/media/radio/Kconfig b/drivers/media/radio/Kconfig
> > > > index d363726e9eb1..8fa403c7149e 100644
> > > > --- a/drivers/media/radio/Kconfig
> > > > +++ b/drivers/media/radio/Kconfig
> > > > @@ -372,7 +372,8 @@ config RADIO_GEMTEK_PROBE
> > > >  
> > > >  config RADIO_MIROPCM20
> > > > tristate "miroSOUND PCM20 radio"
> > > > -   depends on ISA && ISA_DMA_API && VIDEO_V4L2 && SND
> > > > +   depends on ISA || COMPILE_TEST
> > > > +   depends on ISA_DMA_API && VIDEO_V4L2 && SND
> > > > select SND_ISA
> > > > select SND_MIRO
> > > > ---help---
> > > > diff --git a/sound/isa/Kconfig b/sound/isa/Kconfig
> > > > index cb54d9c0a77f..d2a6cdd0395c 100644
> > > > --- a/sound/isa/Kconfig
> > > > +++ b/sound/isa/Kconfig
> > > > @@ -20,7 +20,8 @@ config SND_SB16_DSP
> > > >  
> > > >  menuconfig SND_ISA
> > > > bool "ISA sound devices"
> > > > -   depends on ISA && ISA_DMA_API
> > > > +   depends on ISA || COMPILE_TEST
> > > > +   depends on ISA_DMA_API
> > > > default y
> > > > help
> > > >   Support for sound devices connected via the ISA bus.
> > > > @@ -38,7 +39,7 @@ config SND_ADLIB
> > > >  
> > > >  config SND_AD1816A
> > > > tristate "Analog Devices SoundPort AD1816A"
> > > > -   depends on PNP
> > > > +   depends on PNP && ISA
> > > > select ISAPNP
> > > > select SND_OPL3_LIB
> > > > select SND_MPU401_UART
> > > 
> > > Just from curiosity: what's the reason for this explicit CONFIG_ISA
> > > dependency?  What error did you get?  
> > 
> > Kconfig complains with "select ISAPNP":
> > 
> > WARNING: unmet direct dependencies detected for ISAPNP
> >   Depends on [n]: PNP [=y] && ISA [=n]
> >   Selected by [y]:
> >   - SND_AD1816A [=y] && SOUND [=y] && !UML && SND [=y] && SND_ISA [=y] && 
> > PNP [=y]
> > 
> > Because it is declared as:
> > 
> > config ISAPNP
> > bool "ISA Plug and Play support"
> > depends on ISA
> > 
> > I could have tried to change ISAPNP to depends on ISA || COMPILE_TEST,
> > but I suspect that would touch on yet another subsystem and has
> > the potential to point to other things that need changes, as
> > a lot more drivers will be selected.
> > 
> > Anyway, after a quick look at include/linux/isapnp.h, I suspect
> > that this can work.
> > 
> > I'll run some tests here.
> 
> Yes, removing the ISAPNP dependency if COMPILE_TEST is trivial too.
> 
> Just sent a separate patch to be applied after this one with such
> removal.
> 
> I opted to make it as a separate patch as, if the drivers there
> fail to build on some weird architecture, we won't need to discard
> this one.

OK, then feel free to take my ack:
  Acked-by: Takashi Iwai <ti...@suse.de>

But still it'd be better to mention about the CONFIG_ISA change, even
though it'll be removed again after the ISAPNP COMIPLE_TEST patch.


thanks,

Takashi


Re: [PATCH 3/4] sound, media: allow building ISA drivers it with COMPILE_TEST

2018-04-20 Thread Takashi Iwai
On Fri, 20 Apr 2018 14:51:29 +0200,
Mauro Carvalho Chehab wrote:
> 
> Em Fri, 20 Apr 2018 14:37:46 +0200
> Takashi Iwai <ti...@suse.de> escreveu:
> 
> > On Fri, 20 Apr 2018 14:32:15 +0200,
> > Mauro Carvalho Chehab wrote:
> > > 
> > > All sound drivers that don't depend on PNP can be safelly
> > > build with COMPILE_TEST, as ISA provides function stubs to
> > > be used for such purposes.
> > > 
> > > As a side effect, with this change, the radio-miropcm20
> > > can now be built outside i386 with COMPILE_TEST.
> > > 
> > > Signed-off-by: Mauro Carvalho Chehab <mche...@s-opensource.com>
> > > ---
> > >  drivers/media/radio/Kconfig | 3 ++-
> > >  sound/isa/Kconfig   | 9 +
> > >  2 files changed, 7 insertions(+), 5 deletions(-)
> > > 
> > > diff --git a/drivers/media/radio/Kconfig b/drivers/media/radio/Kconfig
> > > index d363726e9eb1..8fa403c7149e 100644
> > > --- a/drivers/media/radio/Kconfig
> > > +++ b/drivers/media/radio/Kconfig
> > > @@ -372,7 +372,8 @@ config RADIO_GEMTEK_PROBE
> > >  
> > >  config RADIO_MIROPCM20
> > >   tristate "miroSOUND PCM20 radio"
> > > - depends on ISA && ISA_DMA_API && VIDEO_V4L2 && SND
> > > + depends on ISA || COMPILE_TEST
> > > + depends on ISA_DMA_API && VIDEO_V4L2 && SND
> > >   select SND_ISA
> > >   select SND_MIRO
> > >   ---help---
> > > diff --git a/sound/isa/Kconfig b/sound/isa/Kconfig
> > > index cb54d9c0a77f..d2a6cdd0395c 100644
> > > --- a/sound/isa/Kconfig
> > > +++ b/sound/isa/Kconfig
> > > @@ -20,7 +20,8 @@ config SND_SB16_DSP
> > >  
> > >  menuconfig SND_ISA
> > >   bool "ISA sound devices"
> > > - depends on ISA && ISA_DMA_API
> > > + depends on ISA || COMPILE_TEST
> > > + depends on ISA_DMA_API
> > >   default y
> > >   help
> > > Support for sound devices connected via the ISA bus.
> > > @@ -38,7 +39,7 @@ config SND_ADLIB
> > >  
> > >  config SND_AD1816A
> > >   tristate "Analog Devices SoundPort AD1816A"
> > > - depends on PNP
> > > + depends on PNP && ISA
> > >   select ISAPNP
> > >   select SND_OPL3_LIB
> > >   select SND_MPU401_UART  
> > 
> > Just from curiosity: what's the reason for this explicit CONFIG_ISA
> > dependency?  What error did you get?
> 
> Kconfig complains with "select ISAPNP":
> 
> WARNING: unmet direct dependencies detected for ISAPNP
>   Depends on [n]: PNP [=y] && ISA [=n]
>   Selected by [y]:
>   - SND_AD1816A [=y] && SOUND [=y] && !UML && SND [=y] && SND_ISA [=y] && PNP 
> [=y]
> 
> Because it is declared as:
> 
> config ISAPNP
>   bool "ISA Plug and Play support"
> depends on ISA

I see.  Then it'd be better to put this explanations in the changelog
as well.

> I could have tried to change ISAPNP to depends on ISA || COMPILE_TEST,
> but I suspect that would touch on yet another subsystem and has
> the potential to point to other things that need changes, as
> a lot more drivers will be selected.
> 
> Anyway, after a quick look at include/linux/isapnp.h, I suspect
> that this can work.
> 
> I'll run some tests here.

At least a dumb stub is there, so let's hope we can widen the test
coverage :)


thanks,

Takashi


Re: [PATCH 3/4] sound, media: allow building ISA drivers it with COMPILE_TEST

2018-04-20 Thread Takashi Iwai
On Fri, 20 Apr 2018 14:32:15 +0200,
Mauro Carvalho Chehab wrote:
> 
> All sound drivers that don't depend on PNP can be safelly
> build with COMPILE_TEST, as ISA provides function stubs to
> be used for such purposes.
> 
> As a side effect, with this change, the radio-miropcm20
> can now be built outside i386 with COMPILE_TEST.
> 
> Signed-off-by: Mauro Carvalho Chehab 
> ---
>  drivers/media/radio/Kconfig | 3 ++-
>  sound/isa/Kconfig   | 9 +
>  2 files changed, 7 insertions(+), 5 deletions(-)
> 
> diff --git a/drivers/media/radio/Kconfig b/drivers/media/radio/Kconfig
> index d363726e9eb1..8fa403c7149e 100644
> --- a/drivers/media/radio/Kconfig
> +++ b/drivers/media/radio/Kconfig
> @@ -372,7 +372,8 @@ config RADIO_GEMTEK_PROBE
>  
>  config RADIO_MIROPCM20
>   tristate "miroSOUND PCM20 radio"
> - depends on ISA && ISA_DMA_API && VIDEO_V4L2 && SND
> + depends on ISA || COMPILE_TEST
> + depends on ISA_DMA_API && VIDEO_V4L2 && SND
>   select SND_ISA
>   select SND_MIRO
>   ---help---
> diff --git a/sound/isa/Kconfig b/sound/isa/Kconfig
> index cb54d9c0a77f..d2a6cdd0395c 100644
> --- a/sound/isa/Kconfig
> +++ b/sound/isa/Kconfig
> @@ -20,7 +20,8 @@ config SND_SB16_DSP
>  
>  menuconfig SND_ISA
>   bool "ISA sound devices"
> - depends on ISA && ISA_DMA_API
> + depends on ISA || COMPILE_TEST
> + depends on ISA_DMA_API
>   default y
>   help
> Support for sound devices connected via the ISA bus.
> @@ -38,7 +39,7 @@ config SND_ADLIB
>  
>  config SND_AD1816A
>   tristate "Analog Devices SoundPort AD1816A"
> - depends on PNP
> + depends on PNP && ISA
>   select ISAPNP
>   select SND_OPL3_LIB
>   select SND_MPU401_UART

Just from curiosity: what's the reason for this explicit CONFIG_ISA
dependency?  What error did you get?


thanks,

Takashi

> @@ -66,7 +67,7 @@ config SND_AD1848
>  
>  config SND_ALS100
>   tristate "Diamond Tech. DT-019x and Avance Logic ALSxxx"
> - depends on PNP
> + depends on PNP && ISA
>   select ISAPNP
>   select SND_OPL3_LIB
>   select SND_MPU401_UART
> @@ -107,7 +108,7 @@ config SND_AZT2316
>  
>  config SND_AZT2320
>   tristate "Aztech Systems AZT2320"
> - depends on PNP
> + depends on PNP && ISA
>   select ISAPNP
>   select SND_OPL3_LIB
>   select SND_MPU401_UART
> -- 
> 2.14.3
> 
> 


Re: [alsa-devel] [trivial PATCH] treewide: Align function definition open/close braces

2017-12-18 Thread Takashi Iwai
On Mon, 18 Dec 2017 01:28:44 +0100,
Joe Perches wrote:
> 
> Some functions definitions have either the initial open brace and/or
> the closing brace outside of column 1.
> 
> Move those braces to column 1.
> 
> This allows various function analyzers like gnu complexity to work
> properly for these modified functions.
> 
> Miscellanea:
> 
> o Remove extra trailing ; and blank line from xfs_agf_verify
> 
> Signed-off-by: Joe Perches <j...@perches.com>
> ---
> git diff -w shows no difference other than the above 'Miscellanea'
> 
> (this is against -next, but it applies against Linus' tree
>  with a couple offsets)
> 
>  arch/x86/include/asm/atomic64_32.h   |  2 +-
>  drivers/acpi/custom_method.c |  2 +-
>  drivers/acpi/fan.c   |  2 +-
>  drivers/gpu/drm/amd/display/dc/core/dc.c |  2 +-
>  drivers/media/i2c/msp3400-kthreads.c |  2 +-
>  drivers/message/fusion/mptsas.c  |  2 +-
>  drivers/net/ethernet/qlogic/netxen/netxen_nic_init.c |  2 +-
>  drivers/net/wireless/ath/ath9k/xmit.c|  2 +-
>  drivers/platform/x86/eeepc-laptop.c  |  2 +-
>  drivers/rtc/rtc-ab-b5ze-s3.c |  2 +-
>  drivers/scsi/dpt_i2o.c   |  2 +-
>  drivers/scsi/sym53c8xx_2/sym_glue.c  |  2 +-
>  fs/locks.c   |  2 +-
>  fs/ocfs2/stack_user.c|  2 +-
>  fs/xfs/libxfs/xfs_alloc.c|  5 ++---
>  fs/xfs/xfs_export.c  |  2 +-
>  kernel/audit.c   |  6 +++---
>  kernel/trace/trace_printk.c  |  4 ++--
>  lib/raid6/sse2.c         | 14 +++---
>  sound/soc/fsl/fsl_dma.c  |  2 +-

For sound bits,
  Acked-by: Takashi Iwai <ti...@suse.de>


thanks,

Takashi


Re: [alsa-devel] [PATCH] ALSA: hda - Fix applying MSI dual-codec mobo quirk

2017-06-01 Thread Takashi Iwai
On Thu, 01 Jun 2017 22:58:24 +0200,
Takashi Iwai wrote:
> 
> The previous commit [63691587f7b0: ALSA: hda - Apply dual-codec quirk
> for MSI Z270-Gaming mobo] attempted to apply the existing dual-codec
> quirk for a MSI mobo.  But it turned out that this isn't applied
> properly due to the MSI-vendor quirk before this entry.  I overlooked
> such two MSI entries just because they were put in the wrong position,
> although we have a list ordered by PCI SSID numbers.
> 
> This patch fixes it by rearranging the unordered entries.
> 
> Fixes: 63691587f7b0 ("ALSA: hda - Apply dual-codec quirk for MSI Z270-Gaming 
> mobo")
> Reported-by: Rudolf Schmidt <i...@rudolfschmidt.com>
> Signed-off-by: Takashi Iwai <ti...@suse.de>

Gah, an irrelevant patch I wanted to submit slipped into the patch
series.  Please disregard one, sorry.


Takashi

> ---
>  sound/pci/hda/patch_realtek.c | 4 ++--
>  1 file changed, 2 insertions(+), 2 deletions(-)
> 
> diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c
> index 918e45268915..a57988d617e9 100644
> --- a/sound/pci/hda/patch_realtek.c
> +++ b/sound/pci/hda/patch_realtek.c
> @@ -2324,11 +2324,11 @@ static const struct snd_pci_quirk alc882_fixup_tbl[] 
> = {
>   SND_PCI_QUIRK(0x106b, 0x4a00, "Macbook 5,2", ALC889_FIXUP_MBA11_VREF),
>  
>   SND_PCI_QUIRK(0x1071, 0x8258, "Evesham Voyaeger", ALC882_FIXUP_EAPD),
> - SND_PCI_QUIRK(0x1462, 0x7350, "MSI-7350", ALC889_FIXUP_CD),
> - SND_PCI_QUIRK_VENDOR(0x1462, "MSI", ALC882_FIXUP_GPIO3),
>   SND_PCI_QUIRK(0x1458, 0xa002, "Gigabyte EP45-DS3/Z87X-UD3H", 
> ALC889_FIXUP_FRONT_HP_NO_PRESENCE),
>   SND_PCI_QUIRK(0x1458, 0xa0b8, "Gigabyte AZ370-Gaming", 
> ALC1220_FIXUP_GB_DUAL_CODECS),
> + SND_PCI_QUIRK(0x1462, 0x7350, "MSI-7350", ALC889_FIXUP_CD),
>   SND_PCI_QUIRK(0x1462, 0xda57, "MSI Z270-Gaming", 
> ALC1220_FIXUP_GB_DUAL_CODECS),
> + SND_PCI_QUIRK_VENDOR(0x1462, "MSI", ALC882_FIXUP_GPIO3),
>   SND_PCI_QUIRK(0x147b, 0x107a, "Abit AW9D-MAX", 
> ALC882_FIXUP_ABIT_AW9D_MAX),
>   SND_PCI_QUIRK_VENDOR(0x1558, "Clevo laptop", ALC882_FIXUP_EAPD),
>   SND_PCI_QUIRK(0x161f, 0x2054, "Medion laptop", ALC883_FIXUP_EAPD),
> -- 
> 2.13.0
> 
> ___
> Alsa-devel mailing list
> alsa-de...@alsa-project.org
> http://mailman.alsa-project.org/mailman/listinfo/alsa-devel
> 


[PATCH v2 10/27] ALSA: hdsp: Convert to the new PCM ops

2017-06-01 Thread Takashi Iwai
Replace the copy and the silence ops with the new PCM ops.
The conversion is straightforward with standard helper functions.

Signed-off-by: Takashi Iwai <ti...@suse.de>
---
 sound/pci/rme9652/hdsp.c | 67 
 1 file changed, 50 insertions(+), 17 deletions(-)

diff --git a/sound/pci/rme9652/hdsp.c b/sound/pci/rme9652/hdsp.c
index fc0face6cdc6..b9644e0e 100644
--- a/sound/pci/rme9652/hdsp.c
+++ b/sound/pci/rme9652/hdsp.c
@@ -3913,42 +3913,73 @@ static char *hdsp_channel_buffer_location(struct hdsp 
*hdsp,
return hdsp->playback_buffer + (mapped_channel * 
HDSP_CHANNEL_BUFFER_BYTES);
 }
 
-static int snd_hdsp_playback_copy(struct snd_pcm_substream *substream, int 
channel,
- snd_pcm_uframes_t pos, void __user *src, 
snd_pcm_uframes_t count)
+static int snd_hdsp_playback_copy(struct snd_pcm_substream *substream,
+ int channel, unsigned long pos,
+ void __user *src, unsigned long count)
 {
struct hdsp *hdsp = snd_pcm_substream_chip(substream);
char *channel_buf;
 
-   if (snd_BUG_ON(pos + count > HDSP_CHANNEL_BUFFER_BYTES / 4))
+   if (snd_BUG_ON(pos + count > HDSP_CHANNEL_BUFFER_BYTES))
return -EINVAL;
 
channel_buf = hdsp_channel_buffer_location (hdsp, 
substream->pstr->stream, channel);
if (snd_BUG_ON(!channel_buf))
return -EIO;
-   if (copy_from_user(channel_buf + pos * 4, src, count * 4))
+   if (copy_from_user(channel_buf + pos, src, count))
return -EFAULT;
-   return count;
+   return 0;
 }
 
-static int snd_hdsp_capture_copy(struct snd_pcm_substream *substream, int 
channel,
-snd_pcm_uframes_t pos, void __user *dst, 
snd_pcm_uframes_t count)
+static int snd_hdsp_playback_copy_kernel(struct snd_pcm_substream *substream,
+int channel, unsigned long pos,
+void *src, unsigned long count)
 {
struct hdsp *hdsp = snd_pcm_substream_chip(substream);
char *channel_buf;
 
-   if (snd_BUG_ON(pos + count > HDSP_CHANNEL_BUFFER_BYTES / 4))
+   channel_buf = hdsp_channel_buffer_location(hdsp, 
substream->pstr->stream, channel);
+   if (snd_BUG_ON(!channel_buf))
+   return -EIO;
+   memcpy(channel_buf + pos, src, count);
+   return 0;
+}
+
+static int snd_hdsp_capture_copy(struct snd_pcm_substream *substream,
+int channel, unsigned long pos,
+void __user *dst, unsigned long count)
+{
+   struct hdsp *hdsp = snd_pcm_substream_chip(substream);
+   char *channel_buf;
+
+   if (snd_BUG_ON(pos + count > HDSP_CHANNEL_BUFFER_BYTES))
return -EINVAL;
 
channel_buf = hdsp_channel_buffer_location (hdsp, 
substream->pstr->stream, channel);
if (snd_BUG_ON(!channel_buf))
return -EIO;
-   if (copy_to_user(dst, channel_buf + pos * 4, count * 4))
+   if (copy_to_user(dst, channel_buf + pos, count))
return -EFAULT;
-   return count;
+   return 0;
 }
 
-static int snd_hdsp_hw_silence(struct snd_pcm_substream *substream, int 
channel,
- snd_pcm_uframes_t pos, snd_pcm_uframes_t 
count)
+static int snd_hdsp_capture_copy_kernel(struct snd_pcm_substream *substream,
+   int channel, unsigned long pos,
+   void *dst, unsigned long count)
+{
+   struct hdsp *hdsp = snd_pcm_substream_chip(substream);
+   char *channel_buf;
+
+   channel_buf = hdsp_channel_buffer_location(hdsp, 
substream->pstr->stream, channel);
+   if (snd_BUG_ON(!channel_buf))
+   return -EIO;
+   memcpy(dst, channel_buf + pos, count);
+   return 0;
+}
+
+static int snd_hdsp_hw_silence(struct snd_pcm_substream *substream,
+  int channel, unsigned long pos,
+  unsigned long count)
 {
struct hdsp *hdsp = snd_pcm_substream_chip(substream);
char *channel_buf;
@@ -3956,8 +3987,8 @@ static int snd_hdsp_hw_silence(struct snd_pcm_substream 
*substream, int channel,
channel_buf = hdsp_channel_buffer_location (hdsp, 
substream->pstr->stream, channel);
if (snd_BUG_ON(!channel_buf))
return -EIO;
-   memset(channel_buf + pos * 4, 0, count * 4);
-   return count;
+   memset(channel_buf + pos, 0, count);
+   return 0;
 }
 
 static int snd_hdsp_reset(struct snd_pcm_substream *substream)
@@ -4869,8 +4900,9 @@ static const struct snd_pcm_ops snd_hdsp_playback_ops = {
.prepare =  snd_hdsp_prepare,
.trigger =  snd_hdsp_trigger,
.pointer =  snd_hdsp_hw_pointer,
-   .copy

[PATCH v2 23/27] ALSA: pcm: Direct in-kernel read/write support

2017-06-01 Thread Takashi Iwai
Now all materials are ready, let's allow the direct in-kernel
read/write, i.e. a kernel-space buffer is passed for read or write,
instead of the normal user-space buffer.  This feature is used by OSS
layer and UAC1 driver, for example.

The __snd_pcm_lib_xfer() takes in_kernel argument that indicates the
in-kernel buffer copy.  When this flag is set, another transfer code
is used.  It's either via copy_kernel PCM ops or the normal memcpy(),
depending on the driver setup.

As external API, snd_pcm_kernel_read(), *_write() and other variants
are provided.

That's all.  This support is really simple because of the code
refactoring until now.

Signed-off-by: Takashi Iwai <ti...@suse.de>
---
 include/sound/pcm.h  | 38 +-
 sound/core/pcm_lib.c | 26 +-
 2 files changed, 58 insertions(+), 6 deletions(-)

diff --git a/include/sound/pcm.h b/include/sound/pcm.h
index 173c6a6ebf35..e3a7269824c7 100644
--- a/include/sound/pcm.h
+++ b/include/sound/pcm.h
@@ -1090,34 +1090,62 @@ void snd_pcm_playback_silence(struct snd_pcm_substream 
*substream, snd_pcm_ufram
 void snd_pcm_period_elapsed(struct snd_pcm_substream *substream);
 snd_pcm_sframes_t __snd_pcm_lib_xfer(struct snd_pcm_substream *substream,
 void *buf, bool interleaved,
-snd_pcm_uframes_t frames);
+snd_pcm_uframes_t frames, bool in_kernel);
 
 static inline snd_pcm_sframes_t
 snd_pcm_lib_write(struct snd_pcm_substream *substream,
  const void __user *buf, snd_pcm_uframes_t frames)
 {
-   return __snd_pcm_lib_xfer(substream, (void *)buf, true, frames);
+   return __snd_pcm_lib_xfer(substream, (void *)buf, true, frames, false);
 }
 
 static inline snd_pcm_sframes_t
 snd_pcm_lib_read(struct snd_pcm_substream *substream,
 void __user *buf, snd_pcm_uframes_t frames)
 {
-   return __snd_pcm_lib_xfer(substream, (void *)buf, true, frames);
+   return __snd_pcm_lib_xfer(substream, (void *)buf, true, frames, false);
 }
 
 static inline snd_pcm_sframes_t
 snd_pcm_lib_writev(struct snd_pcm_substream *substream,
   void __user **bufs, snd_pcm_uframes_t frames)
 {
-   return __snd_pcm_lib_xfer(substream, (void *)bufs, false, frames);
+   return __snd_pcm_lib_xfer(substream, (void *)bufs, false, frames, 
false);
 }
 
 static inline snd_pcm_sframes_t
 snd_pcm_lib_readv(struct snd_pcm_substream *substream,
  void __user **bufs, snd_pcm_uframes_t frames)
 {
-   return __snd_pcm_lib_xfer(substream, (void *)bufs, false, frames);
+   return __snd_pcm_lib_xfer(substream, (void *)bufs, false, frames, 
false);
+}
+
+static inline snd_pcm_sframes_t
+snd_pcm_kernel_write(struct snd_pcm_substream *substream,
+const void *buf, snd_pcm_uframes_t frames)
+{
+   return __snd_pcm_lib_xfer(substream, (void *)buf, true, frames, true);
+}
+
+static inline snd_pcm_sframes_t
+snd_pcm_kernel_read(struct snd_pcm_substream *substream,
+   void *buf, snd_pcm_uframes_t frames)
+{
+   return __snd_pcm_lib_xfer(substream, buf, true, frames, true);
+}
+
+static inline snd_pcm_sframes_t
+snd_pcm_kernel_writev(struct snd_pcm_substream *substream,
+ void **bufs, snd_pcm_uframes_t frames)
+{
+   return __snd_pcm_lib_xfer(substream, bufs, false, frames, true);
+}
+
+static inline snd_pcm_sframes_t
+snd_pcm_kernel_readv(struct snd_pcm_substream *substream,
+void **bufs, snd_pcm_uframes_t frames)
+{
+   return __snd_pcm_lib_xfer(substream, bufs, false, frames, true);
 }
 
 extern const struct snd_pcm_hw_constraint_list snd_pcm_known_rates;
diff --git a/sound/core/pcm_lib.c b/sound/core/pcm_lib.c
index a592d3308474..ba08b246d153 100644
--- a/sound/core/pcm_lib.c
+++ b/sound/core/pcm_lib.c
@@ -1992,6 +1992,15 @@ static int default_write_copy(struct snd_pcm_substream 
*substream,
return 0;
 }
 
+/* default copy_kernel ops for write */
+static int default_write_copy_kernel(struct snd_pcm_substream *substream,
+int channel, unsigned long hwoff,
+void *buf, unsigned long bytes)
+{
+   memcpy(get_dma_ptr(substream->runtime, channel, hwoff), buf, bytes);
+   return 0;
+}
+
 /* fill silence instead of copy data; called as a transfer helper
  * from __snd_pcm_lib_write() or directly from noninterleaved_copy() when
  * a NULL buffer is passed
@@ -2025,6 +2034,15 @@ static int default_read_copy(struct snd_pcm_substream 
*substream,
return 0;
 }
 
+/* default copy_kernel ops for read */
+static int default_read_copy_kernel(struct snd_pcm_substream *substream,
+   int channel, unsigned long hwoff,
+   void *buf, unsigned long bytes)
+{
+   memcpy(buf, get_dma_ptr(substream->runtime, channel, h

[PATCH v2 17/27] ALSA: pcm: Check PCM state by a common helper function

2017-06-01 Thread Takashi Iwai
Signed-off-by: Takashi Iwai <ti...@suse.de>
---
 sound/core/pcm_lib.c | 81 +++-
 1 file changed, 29 insertions(+), 52 deletions(-)

diff --git a/sound/core/pcm_lib.c b/sound/core/pcm_lib.c
index 0db8d4e0fca2..e4f5c43b6448 100644
--- a/sound/core/pcm_lib.c
+++ b/sound/core/pcm_lib.c
@@ -2017,6 +2017,22 @@ typedef int (*transfer_f)(struct snd_pcm_substream 
*substream, unsigned int hwof
  unsigned long data, unsigned int off,
  snd_pcm_uframes_t size);
 
+static int pcm_accessible_state(struct snd_pcm_runtime *runtime)
+{
+   switch (runtime->status->state) {
+   case SNDRV_PCM_STATE_PREPARED:
+   case SNDRV_PCM_STATE_RUNNING:
+   case SNDRV_PCM_STATE_PAUSED:
+   return 0;
+   case SNDRV_PCM_STATE_XRUN:
+   return -EPIPE;
+   case SNDRV_PCM_STATE_SUSPENDED:
+   return -ESTRPIPE;
+   default:
+   return -EBADFD;
+   }
+}
+
 static snd_pcm_sframes_t snd_pcm_lib_write1(struct snd_pcm_substream 
*substream, 
unsigned long data,
snd_pcm_uframes_t size,
@@ -2033,21 +2049,9 @@ static snd_pcm_sframes_t snd_pcm_lib_write1(struct 
snd_pcm_substream *substream,
return 0;
 
snd_pcm_stream_lock_irq(substream);
-   switch (runtime->status->state) {
-   case SNDRV_PCM_STATE_PREPARED:
-   case SNDRV_PCM_STATE_RUNNING:
-   case SNDRV_PCM_STATE_PAUSED:
-   break;
-   case SNDRV_PCM_STATE_XRUN:
-   err = -EPIPE;
-   goto _end_unlock;
-   case SNDRV_PCM_STATE_SUSPENDED:
-   err = -ESTRPIPE;
-   goto _end_unlock;
-   default:
-   err = -EBADFD;
+   err = pcm_accessible_state(runtime);
+   if (err < 0)
goto _end_unlock;
-   }
 
runtime->twake = runtime->control->avail_min ? : 1;
if (runtime->status->state == SNDRV_PCM_STATE_RUNNING)
@@ -2083,16 +2087,9 @@ static snd_pcm_sframes_t snd_pcm_lib_write1(struct 
snd_pcm_substream *substream,
snd_pcm_stream_lock_irq(substream);
if (err < 0)
goto _end_unlock;
-   switch (runtime->status->state) {
-   case SNDRV_PCM_STATE_XRUN:
-   err = -EPIPE;
-   goto _end_unlock;
-   case SNDRV_PCM_STATE_SUSPENDED:
-   err = -ESTRPIPE;
+   err = pcm_accessible_state(runtime);
+   if (err < 0)
goto _end_unlock;
-   default:
-   break;
-   }
appl_ptr += frames;
if (appl_ptr >= runtime->boundary)
appl_ptr -= runtime->boundary;
@@ -2263,27 +2260,14 @@ static snd_pcm_sframes_t snd_pcm_lib_read1(struct 
snd_pcm_substream *substream,
return 0;
 
snd_pcm_stream_lock_irq(substream);
-   switch (runtime->status->state) {
-   case SNDRV_PCM_STATE_PREPARED:
-   if (size >= runtime->start_threshold) {
-   err = snd_pcm_start(substream);
-   if (err < 0)
-   goto _end_unlock;
-   }
-   break;
-   case SNDRV_PCM_STATE_DRAINING:
-   case SNDRV_PCM_STATE_RUNNING:
-   case SNDRV_PCM_STATE_PAUSED:
-   break;
-   case SNDRV_PCM_STATE_XRUN:
-   err = -EPIPE;
-   goto _end_unlock;
-   case SNDRV_PCM_STATE_SUSPENDED:
-   err = -ESTRPIPE;
-   goto _end_unlock;
-   default:
-   err = -EBADFD;
+   err = pcm_accessible_state(runtime);
+   if (err < 0)
goto _end_unlock;
+   if (runtime->status->state == SNDRV_PCM_STATE_PREPARED &&
+   size >= runtime->start_threshold) {
+   err = snd_pcm_start(substream);
+   if (err < 0)
+   goto _end_unlock;
}
 
runtime->twake = runtime->control->avail_min ? : 1;
@@ -2327,16 +2311,9 @@ static snd_pcm_sframes_t snd_pcm_lib_read1(struct 
snd_pcm_substream *substream,
snd_pcm_stream_lock_irq(substream);
if (err < 0)
goto _end_unlock;
-   switch (runtime->status->state) {
-   case SNDRV_PCM_STATE_XRUN:
-   err = -EPIPE;
-   goto _end_unlock;
-   case SNDRV_PCM_STATE_SUSPENDED:
-   err = -ESTRPIPE;
+   err = pcm_accessible_state(runtime);
+   if (err < 0)
goto _end_unlock;
-   default:
-  

[PATCH v2 03/27] ALSA: dummy: Convert to new PCM copy ops

2017-06-01 Thread Takashi Iwai
It's a dummy ops, so just replacing it.

Signed-off-by: Takashi Iwai <ti...@suse.de>
---
 sound/drivers/dummy.c | 20 ++--
 1 file changed, 14 insertions(+), 6 deletions(-)

diff --git a/sound/drivers/dummy.c b/sound/drivers/dummy.c
index 172dacd925f5..dd5ed037adf2 100644
--- a/sound/drivers/dummy.c
+++ b/sound/drivers/dummy.c
@@ -644,15 +644,22 @@ static int alloc_fake_buffer(void)
 }
 
 static int dummy_pcm_copy(struct snd_pcm_substream *substream,
- int channel, snd_pcm_uframes_t pos,
- void __user *dst, snd_pcm_uframes_t count)
+ int channel, unsigned long pos,
+ void __user *dst, unsigned long bytes)
+{
+   return 0; /* do nothing */
+}
+
+static int dummy_pcm_copy_kernel(struct snd_pcm_substream *substream,
+int channel, unsigned long pos,
+void *dst, unsigned long bytes)
 {
return 0; /* do nothing */
 }
 
 static int dummy_pcm_silence(struct snd_pcm_substream *substream,
-int channel, snd_pcm_uframes_t pos,
-snd_pcm_uframes_t count)
+int channel, unsigned long pos,
+unsigned long bytes)
 {
return 0; /* do nothing */
 }
@@ -683,8 +690,9 @@ static struct snd_pcm_ops dummy_pcm_ops_no_buf = {
.prepare =  dummy_pcm_prepare,
.trigger =  dummy_pcm_trigger,
.pointer =  dummy_pcm_pointer,
-   .copy = dummy_pcm_copy,
-   .silence =  dummy_pcm_silence,
+   .copy_user =dummy_pcm_copy,
+   .copy_kernel =  dummy_pcm_copy_kernel,
+   .fill_silence = dummy_pcm_silence,
.page = dummy_pcm_page,
 };
 
-- 
2.13.0



[PATCH v2 02/27] ALSA: pcm: Introduce copy_user, copy_kernel and fill_silence ops

2017-06-01 Thread Takashi Iwai
For supporting the explicit in-kernel copy of PCM buffer data, and
also for further code refactoring, three new PCM ops, copy_user,
copy_kernel and fill_silence, are introduced.  The old copy and
silence ops will be deprecated and removed later once when all callers
are converted.

The copy_kernel ops is the new one, and it's supposed to transfer the
PCM data from the given kernel buffer to the hardware ring-buffer (or
vice-versa depending on the stream direction), while the copy_user ops
is equivalent with the former copy ops, to transfer the data from the
user-space buffer.

The major difference of the new copy_* and fill_silence ops from the
previous ops is that the new ops take bytes instead of frames for size
and position arguments.  It has two merits: first, it allows the
callback implementation often simpler (just call directly memcpy() &
co), and second, it may unify the implementations of both interleaved
and non-interleaved cases, as we'll see in the later patch.

As of this stage, copy_kernel ops isn't referred yet, but only
copy_user is used.

Signed-off-by: Takashi Iwai <ti...@suse.de>
---
 include/sound/pcm.h  |  7 +
 sound/core/pcm_lib.c | 89 +++-
 sound/soc/soc-pcm.c  |  3 ++
 3 files changed, 84 insertions(+), 15 deletions(-)

diff --git a/include/sound/pcm.h b/include/sound/pcm.h
index c609b891c4c2..a065415191d8 100644
--- a/include/sound/pcm.h
+++ b/include/sound/pcm.h
@@ -83,6 +83,13 @@ struct snd_pcm_ops {
void __user *buf, snd_pcm_uframes_t count);
int (*silence)(struct snd_pcm_substream *substream, int channel, 
   snd_pcm_uframes_t pos, snd_pcm_uframes_t count);
+   int (*fill_silence)(struct snd_pcm_substream *substream, int channel,
+   unsigned long pos, unsigned long bytes);
+   int (*copy_user)(struct snd_pcm_substream *substream, int channel,
+unsigned long pos, void __user *buf,
+unsigned long bytes);
+   int (*copy_kernel)(struct snd_pcm_substream *substream, int channel,
+  unsigned long pos, void *buf, unsigned long bytes);
struct page *(*page)(struct snd_pcm_substream *substream,
 unsigned long offset);
int (*mmap)(struct snd_pcm_substream *substream, struct vm_area_struct 
*vma);
diff --git a/sound/core/pcm_lib.c b/sound/core/pcm_lib.c
index ab4b1d1e44ee..9334fc2c20c8 100644
--- a/sound/core/pcm_lib.c
+++ b/sound/core/pcm_lib.c
@@ -55,6 +55,8 @@ void snd_pcm_playback_silence(struct snd_pcm_substream 
*substream, snd_pcm_ufram
 {
struct snd_pcm_runtime *runtime = substream->runtime;
snd_pcm_uframes_t frames, ofs, transfer;
+   char *hwbuf;
+   int err;
 
if (runtime->silence_size < runtime->boundary) {
snd_pcm_sframes_t noise_dist, n;
@@ -109,27 +111,37 @@ void snd_pcm_playback_silence(struct snd_pcm_substream 
*substream, snd_pcm_ufram
transfer = ofs + frames > runtime->buffer_size ? 
runtime->buffer_size - ofs : frames;
if (runtime->access == SNDRV_PCM_ACCESS_RW_INTERLEAVED ||
runtime->access == SNDRV_PCM_ACCESS_MMAP_INTERLEAVED) {
-   if (substream->ops->silence) {
-   int err;
+   if (substream->ops->fill_silence) {
+   err = substream->ops->fill_silence(substream, 0,
+  
frames_to_bytes(runtime, ofs),
+  
frames_to_bytes(runtime, transfer));
+   snd_BUG_ON(err < 0);
+   } else if (substream->ops->silence) {
err = substream->ops->silence(substream, -1, 
ofs, transfer);
snd_BUG_ON(err < 0);
} else {
-   char *hwbuf = runtime->dma_area + 
frames_to_bytes(runtime, ofs);
+   hwbuf = runtime->dma_area + 
frames_to_bytes(runtime, ofs);
snd_pcm_format_set_silence(runtime->format, 
hwbuf, transfer * runtime->channels);
}
} else {
unsigned int c;
unsigned int channels = runtime->channels;
-   if (substream->ops->silence) {
+   if (substream->ops->fill_silence) {
+   for (c = 0; c < channels; ++c) {
+   err = 
substream->ops->fill_silence(substream, c,
+  
samples_to_bytes(runtime, ofs),
+

[PATCH v2 15/27] [media] solo6x10: Convert to the new PCM ops

2017-06-01 Thread Takashi Iwai
Replace the copy and the silence ops with the new PCM ops.
The device supports only 1 channel and 8bit sample, so it's always
bytes=frames, and we need no conversion of unit in the callback.
Also, it's a capture stream, thus no silence is needed.

Signed-off-by: Takashi Iwai <ti...@suse.de>
---
 drivers/media/pci/solo6x10/solo6x10-g723.c | 32 ++
 1 file changed, 24 insertions(+), 8 deletions(-)

diff --git a/drivers/media/pci/solo6x10/solo6x10-g723.c 
b/drivers/media/pci/solo6x10/solo6x10-g723.c
index 36e93540bb49..3ca947092775 100644
--- a/drivers/media/pci/solo6x10/solo6x10-g723.c
+++ b/drivers/media/pci/solo6x10/solo6x10-g723.c
@@ -223,9 +223,9 @@ static snd_pcm_uframes_t snd_solo_pcm_pointer(struct 
snd_pcm_substream *ss)
return idx * G723_FRAMES_PER_PAGE;
 }
 
-static int snd_solo_pcm_copy(struct snd_pcm_substream *ss, int channel,
-snd_pcm_uframes_t pos, void __user *dst,
-snd_pcm_uframes_t count)
+static int __snd_solo_pcm_copy(struct snd_pcm_substream *ss,
+  unsigned long pos, void *dst,
+  unsigned long count, bool in_kernel)
 {
struct solo_snd_pcm *solo_pcm = snd_pcm_substream_chip(ss);
struct solo_dev *solo_dev = solo_pcm->solo_dev;
@@ -242,16 +242,31 @@ static int snd_solo_pcm_copy(struct snd_pcm_substream 
*ss, int channel,
if (err)
return err;
 
-   err = copy_to_user(dst + (i * G723_PERIOD_BYTES),
-  solo_pcm->g723_buf, G723_PERIOD_BYTES);
-
-   if (err)
+   if (in_kernel)
+   memcpy(dst, solo_pcm->g723_buf, G723_PERIOD_BYTES);
+   else if (copy_to_user((void __user *)dst,
+ solo_pcm->g723_buf, G723_PERIOD_BYTES))
return -EFAULT;
+   dst += G723_PERIOD_BYTES;
}
 
return 0;
 }
 
+static int snd_solo_pcm_copy_user(struct snd_pcm_substream *ss, int channel,
+ unsigned long pos, void __user *dst,
+ unsigned long count)
+{
+   return __snd_solo_pcm_copy(ss, pos, (void *)dst, count, false);
+}
+
+static int snd_solo_pcm_copy_kernel(struct snd_pcm_substream *ss, int channel,
+   unsigned long pos, void *dst,
+   unsigned long count)
+{
+   return __snd_solo_pcm_copy(ss, pos, dst, count, true);
+}
+
 static const struct snd_pcm_ops snd_solo_pcm_ops = {
.open = snd_solo_pcm_open,
.close = snd_solo_pcm_close,
@@ -261,7 +276,8 @@ static const struct snd_pcm_ops snd_solo_pcm_ops = {
.prepare = snd_solo_pcm_prepare,
.trigger = snd_solo_pcm_trigger,
.pointer = snd_solo_pcm_pointer,
-   .copy = snd_solo_pcm_copy,
+   .copy_user = snd_solo_pcm_copy_user,
+   .copy_kernel = snd_solo_pcm_copy_kernel,
 };
 
 static int snd_solo_capture_volume_info(struct snd_kcontrol *kcontrol,
-- 
2.13.0



[PATCH] ALSA: hda - Fix applying MSI dual-codec mobo quirk

2017-06-01 Thread Takashi Iwai
The previous commit [63691587f7b0: ALSA: hda - Apply dual-codec quirk
for MSI Z270-Gaming mobo] attempted to apply the existing dual-codec
quirk for a MSI mobo.  But it turned out that this isn't applied
properly due to the MSI-vendor quirk before this entry.  I overlooked
such two MSI entries just because they were put in the wrong position,
although we have a list ordered by PCI SSID numbers.

This patch fixes it by rearranging the unordered entries.

Fixes: 63691587f7b0 ("ALSA: hda - Apply dual-codec quirk for MSI Z270-Gaming 
mobo")
Reported-by: Rudolf Schmidt <i...@rudolfschmidt.com>
Signed-off-by: Takashi Iwai <ti...@suse.de>
---
 sound/pci/hda/patch_realtek.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c
index 918e45268915..a57988d617e9 100644
--- a/sound/pci/hda/patch_realtek.c
+++ b/sound/pci/hda/patch_realtek.c
@@ -2324,11 +2324,11 @@ static const struct snd_pci_quirk alc882_fixup_tbl[] = {
SND_PCI_QUIRK(0x106b, 0x4a00, "Macbook 5,2", ALC889_FIXUP_MBA11_VREF),
 
SND_PCI_QUIRK(0x1071, 0x8258, "Evesham Voyaeger", ALC882_FIXUP_EAPD),
-   SND_PCI_QUIRK(0x1462, 0x7350, "MSI-7350", ALC889_FIXUP_CD),
-   SND_PCI_QUIRK_VENDOR(0x1462, "MSI", ALC882_FIXUP_GPIO3),
SND_PCI_QUIRK(0x1458, 0xa002, "Gigabyte EP45-DS3/Z87X-UD3H", 
ALC889_FIXUP_FRONT_HP_NO_PRESENCE),
SND_PCI_QUIRK(0x1458, 0xa0b8, "Gigabyte AZ370-Gaming", 
ALC1220_FIXUP_GB_DUAL_CODECS),
+   SND_PCI_QUIRK(0x1462, 0x7350, "MSI-7350", ALC889_FIXUP_CD),
SND_PCI_QUIRK(0x1462, 0xda57, "MSI Z270-Gaming", 
ALC1220_FIXUP_GB_DUAL_CODECS),
+   SND_PCI_QUIRK_VENDOR(0x1462, "MSI", ALC882_FIXUP_GPIO3),
SND_PCI_QUIRK(0x147b, 0x107a, "Abit AW9D-MAX", 
ALC882_FIXUP_ABIT_AW9D_MAX),
SND_PCI_QUIRK_VENDOR(0x1558, "Clevo laptop", ALC882_FIXUP_EAPD),
SND_PCI_QUIRK(0x161f, 0x2054, "Medion laptop", ALC883_FIXUP_EAPD),
-- 
2.13.0



[PATCH v2 08/27] ALSA: rme96: Convert to the new PCM ops

2017-06-01 Thread Takashi Iwai
Replace the copy and the silence ops with the new PCM ops.
The conversion is straightforward with standard helper functions, and
now we can drop the bytes <-> frames conversions in callbacks.

Signed-off-by: Takashi Iwai <ti...@suse.de>
---
 sound/pci/rme96.c | 70 ++-
 1 file changed, 44 insertions(+), 26 deletions(-)

diff --git a/sound/pci/rme96.c b/sound/pci/rme96.c
index 05b9da30990d..24f1349a8e1b 100644
--- a/sound/pci/rme96.c
+++ b/sound/pci/rme96.c
@@ -327,13 +327,10 @@ snd_rme96_capture_ptr(struct rme96 *rme96)
 
 static int
 snd_rme96_playback_silence(struct snd_pcm_substream *substream,
-  int channel, /* not used (interleaved data) */
-  snd_pcm_uframes_t pos,
-  snd_pcm_uframes_t count)
+  int channel, unsigned long pos, unsigned long count)
 {
struct rme96 *rme96 = snd_pcm_substream_chip(substream);
-   count <<= rme96->playback_frlog;
-   pos <<= rme96->playback_frlog;
+
memset_io(rme96->iobase + RME96_IO_PLAY_BUFFER + pos,
  0, count);
return 0;
@@ -341,32 +338,49 @@ snd_rme96_playback_silence(struct snd_pcm_substream 
*substream,
 
 static int
 snd_rme96_playback_copy(struct snd_pcm_substream *substream,
-   int channel, /* not used (interleaved data) */
-   snd_pcm_uframes_t pos,
-   void __user *src,
-   snd_pcm_uframes_t count)
+   int channel, unsigned long pos,
+   void __user *src, unsigned long count)
 {
struct rme96 *rme96 = snd_pcm_substream_chip(substream);
-   count <<= rme96->playback_frlog;
-   pos <<= rme96->playback_frlog;
-   return copy_from_user_toio(rme96->iobase + RME96_IO_PLAY_BUFFER + pos, 
src,
-  count);
+
+   return copy_from_user_toio(rme96->iobase + RME96_IO_PLAY_BUFFER + pos,
+  src, count);
+}
+
+static int
+snd_rme96_playback_copy_kernel(struct snd_pcm_substream *substream,
+  int channel, unsigned long pos,
+  void *src, unsigned long count)
+{
+   struct rme96 *rme96 = snd_pcm_substream_chip(substream);
+
+   memcpy_toio(rme96->iobase + RME96_IO_PLAY_BUFFER + pos, src, count);
+   return 0;
 }
 
 static int
 snd_rme96_capture_copy(struct snd_pcm_substream *substream,
-  int channel, /* not used (interleaved data) */
-  snd_pcm_uframes_t pos,
-  void __user *dst,
-  snd_pcm_uframes_t count)
+  int channel, unsigned long pos,
+  void __user *dst, unsigned long count)
 {
struct rme96 *rme96 = snd_pcm_substream_chip(substream);
-   count <<= rme96->capture_frlog;
-   pos <<= rme96->capture_frlog;
-   return copy_to_user_fromio(dst, rme96->iobase + RME96_IO_REC_BUFFER + 
pos,
+
+   return copy_to_user_fromio(dst,
+  rme96->iobase + RME96_IO_REC_BUFFER + pos,
   count);
 }
 
+static int
+snd_rme96_capture_copy_kernel(struct snd_pcm_substream *substream,
+ int channel, unsigned long pos,
+ void *dst, unsigned long count)
+{
+   struct rme96 *rme96 = snd_pcm_substream_chip(substream);
+
+   memcpy_fromio(dst, rme96->iobase + RME96_IO_REC_BUFFER + pos, count);
+   return 0;
+}
+
 /*
  * Digital output capabilities (S/PDIF)
  */
@@ -1513,8 +1527,9 @@ static const struct snd_pcm_ops 
snd_rme96_playback_spdif_ops = {
.prepare =  snd_rme96_playback_prepare,
.trigger =  snd_rme96_playback_trigger,
.pointer =  snd_rme96_playback_pointer,
-   .copy = snd_rme96_playback_copy,
-   .silence =  snd_rme96_playback_silence,
+   .copy_user =snd_rme96_playback_copy,
+   .copy_kernel =  snd_rme96_playback_copy_kernel,
+   .fill_silence = snd_rme96_playback_silence,
.mmap = snd_pcm_lib_mmap_iomem,
 };
 
@@ -1526,7 +1541,8 @@ static const struct snd_pcm_ops 
snd_rme96_capture_spdif_ops = {
.prepare =  snd_rme96_capture_prepare,
.trigger =  snd_rme96_capture_trigger,
.pointer =  snd_rme96_capture_pointer,
-   .copy = snd_rme96_capture_copy,
+   .copy_user =snd_rme96_capture_copy,
+   .copy_kernel =  snd_rme96_capture_copy_kernel,
.mmap = snd_pcm_lib_mmap_iomem,
 };
 
@@ -1538,8 +1554,9 @@ static const struct snd_pcm_ops 
snd_rme96_playback_adat_ops = {
.prepare =  snd_rme96_playback_prepare,
.trigger =  snd_rme96_playback_trigger,
.pointer =  snd_rm

[PATCH v2 04/27] ALSA: es1938: Convert to the new PCM copy ops

2017-06-01 Thread Takashi Iwai
Replace the copy ops with the new copy_user and copy_kernel ops.
It's used only for a capture stream (for some hardware workaround),
thus we need no silence operation.

Signed-off-by: Takashi Iwai <ti...@suse.de>
---
 sound/pci/es1938.c | 33 +
 1 file changed, 25 insertions(+), 8 deletions(-)

diff --git a/sound/pci/es1938.c b/sound/pci/es1938.c
index e8d943071a8c..a544cd52f73a 100644
--- a/sound/pci/es1938.c
+++ b/sound/pci/es1938.c
@@ -839,15 +839,12 @@ static snd_pcm_uframes_t 
snd_es1938_playback_pointer(struct snd_pcm_substream *s
 }
 
 static int snd_es1938_capture_copy(struct snd_pcm_substream *substream,
-  int channel,
-  snd_pcm_uframes_t pos,
-  void __user *dst,
-  snd_pcm_uframes_t count)
+  int channel, unsigned long pos,
+  void __user *dst, unsigned long count)
 {
struct snd_pcm_runtime *runtime = substream->runtime;
struct es1938 *chip = snd_pcm_substream_chip(substream);
-   pos <<= chip->dma1_shift;
-   count <<= chip->dma1_shift;
+
if (snd_BUG_ON(pos + count > chip->dma1_size))
return -EINVAL;
if (pos + count < chip->dma1_size) {
@@ -856,12 +853,31 @@ static int snd_es1938_capture_copy(struct 
snd_pcm_substream *substream,
} else {
if (copy_to_user(dst, runtime->dma_area + pos + 1, count - 1))
return -EFAULT;
-   if (put_user(runtime->dma_area[0], ((unsigned char __user 
*)dst) + count - 1))
+   if (put_user(runtime->dma_area[0],
+((unsigned char __user *)dst) + count - 1))
return -EFAULT;
}
return 0;
 }
 
+static int snd_es1938_capture_copy_kernel(struct snd_pcm_substream *substream,
+ int channel, unsigned long pos,
+ void *dst, unsigned long count)
+{
+   struct snd_pcm_runtime *runtime = substream->runtime;
+   struct es1938 *chip = snd_pcm_substream_chip(substream);
+
+   if (snd_BUG_ON(pos + count > chip->dma1_size))
+   return -EINVAL;
+   if (pos + count < chip->dma1_size) {
+   memcpy(dst, runtime->dma_area + pos + 1, count);
+   } else {
+   memcpy(dst, runtime->dma_area + pos + 1, count - 1);
+   runtime->dma_area[0] = *((unsigned char *)dst + count - 1);
+   }
+   return 0;
+}
+
 /*
  * buffer management
  */
@@ -1012,7 +1028,8 @@ static const struct snd_pcm_ops snd_es1938_capture_ops = {
.prepare =  snd_es1938_capture_prepare,
.trigger =  snd_es1938_capture_trigger,
.pointer =  snd_es1938_capture_pointer,
-   .copy = snd_es1938_capture_copy,
+   .copy_user =snd_es1938_capture_copy,
+   .copy_kernel =  snd_es1938_capture_copy_kernel,
 };
 
 static int snd_es1938_new_pcm(struct es1938 *chip, int device)
-- 
2.13.0



[PATCH v2 19/27] ALSA: pcm: Call directly the common read/write helpers

2017-06-01 Thread Takashi Iwai
Make snd_pcm_lib_read() and *_write() static inline functions that
call the common helper functions directly.  This reduces a slight
amount of codes, and at the same time, it's a preparation for the
further cleanups / fixes.

Signed-off-by: Takashi Iwai <ti...@suse.de>
---
 include/sound/pcm.h  |  43 +++---
 sound/core/pcm_lib.c | 156 ++-
 2 files changed, 89 insertions(+), 110 deletions(-)

diff --git a/include/sound/pcm.h b/include/sound/pcm.h
index 953ebfc83184..cb4eff8ffd2e 100644
--- a/include/sound/pcm.h
+++ b/include/sound/pcm.h
@@ -1088,15 +1088,40 @@ int snd_pcm_update_state(struct snd_pcm_substream 
*substream,
 int snd_pcm_update_hw_ptr(struct snd_pcm_substream *substream);
 void snd_pcm_playback_silence(struct snd_pcm_substream *substream, 
snd_pcm_uframes_t new_hw_ptr);
 void snd_pcm_period_elapsed(struct snd_pcm_substream *substream);
-snd_pcm_sframes_t snd_pcm_lib_write(struct snd_pcm_substream *substream,
-   const void __user *buf,
-   snd_pcm_uframes_t frames);
-snd_pcm_sframes_t snd_pcm_lib_read(struct snd_pcm_substream *substream,
-  void __user *buf, snd_pcm_uframes_t frames);
-snd_pcm_sframes_t snd_pcm_lib_writev(struct snd_pcm_substream *substream,
-void __user **bufs, snd_pcm_uframes_t 
frames);
-snd_pcm_sframes_t snd_pcm_lib_readv(struct snd_pcm_substream *substream,
-   void __user **bufs, snd_pcm_uframes_t 
frames);
+snd_pcm_sframes_t __snd_pcm_lib_write(struct snd_pcm_substream *substream,
+ void *buf, bool interleaved,
+ snd_pcm_uframes_t frames);
+snd_pcm_sframes_t __snd_pcm_lib_read(struct snd_pcm_substream *substream,
+void *buf, bool interleaved,
+snd_pcm_uframes_t frames);
+
+static inline snd_pcm_sframes_t
+snd_pcm_lib_write(struct snd_pcm_substream *substream,
+ const void __user *buf, snd_pcm_uframes_t frames)
+{
+   return __snd_pcm_lib_write(substream, (void *)buf, true, frames);
+}
+
+static inline snd_pcm_sframes_t
+snd_pcm_lib_read(struct snd_pcm_substream *substream,
+void __user *buf, snd_pcm_uframes_t frames)
+{
+   return __snd_pcm_lib_read(substream, (void *)buf, true, frames);
+}
+
+static inline snd_pcm_sframes_t
+snd_pcm_lib_writev(struct snd_pcm_substream *substream,
+  void __user **bufs, snd_pcm_uframes_t frames)
+{
+   return __snd_pcm_lib_write(substream, (void *)bufs, false, frames);
+}
+
+static inline snd_pcm_sframes_t
+snd_pcm_lib_readv(struct snd_pcm_substream *substream,
+ void __user **bufs, snd_pcm_uframes_t frames)
+{
+   return __snd_pcm_lib_read(substream, (void *)bufs, false, frames);
+}
 
 extern const struct snd_pcm_hw_constraint_list snd_pcm_known_rates;
 
diff --git a/sound/core/pcm_lib.c b/sound/core/pcm_lib.c
index 1f5251cca607..1bd7244324d5 100644
--- a/sound/core/pcm_lib.c
+++ b/sound/core/pcm_lib.c
@@ -1992,12 +1992,12 @@ static int wait_for_avail(struct snd_pcm_substream 
*substream,
 }

 typedef int (*transfer_f)(struct snd_pcm_substream *substream, unsigned int 
hwoff,
- unsigned long data, unsigned int off,
+ void  *data, unsigned int off,
  snd_pcm_uframes_t size);
 
 static int snd_pcm_lib_write_transfer(struct snd_pcm_substream *substream,
  unsigned int hwoff,
- unsigned long data, unsigned int off,
+ void *data, unsigned int off,
  snd_pcm_uframes_t frames)
 {
struct snd_pcm_runtime *runtime = substream->runtime;
@@ -2019,7 +2019,7 @@ static int snd_pcm_lib_write_transfer(struct 
snd_pcm_substream *substream,
  
 static int snd_pcm_lib_writev_transfer(struct snd_pcm_substream *substream,
   unsigned int hwoff,
-  unsigned long data, unsigned int off,
+  void *data, unsigned int off,
   snd_pcm_uframes_t frames)
 {
struct snd_pcm_runtime *runtime = substream->runtime;
@@ -2096,21 +2096,39 @@ static int pcm_accessible_state(struct snd_pcm_runtime 
*runtime)
}
 }
 
-static snd_pcm_sframes_t snd_pcm_lib_write1(struct snd_pcm_substream 
*substream, 
-   unsigned long data,
-   snd_pcm_uframes_t size,
-   int nonblock,
-   transfer_f transfer)
+snd_pcm_sframes_t __snd_pcm_lib_write(struct snd_pcm_substrea

[PATCH v2 14/27] ASoC: blackfin: Convert to the new PCM ops

2017-06-01 Thread Takashi Iwai
Replace the copy and the silence ops with the new PCM ops.
In AC97 and I2S-TDM mode, we need to convert back to frames, but
otherwise the conversion is pretty straightforward.

Signed-off-by: Takashi Iwai <ti...@suse.de>
---
 sound/soc/blackfin/bf5xx-ac97-pcm.c | 27 +++
 sound/soc/blackfin/bf5xx-i2s-pcm.c  | 36 
 2 files changed, 43 insertions(+), 20 deletions(-)

diff --git a/sound/soc/blackfin/bf5xx-ac97-pcm.c 
b/sound/soc/blackfin/bf5xx-ac97-pcm.c
index 02ad2606fa19..913e29275f4e 100644
--- a/sound/soc/blackfin/bf5xx-ac97-pcm.c
+++ b/sound/soc/blackfin/bf5xx-ac97-pcm.c
@@ -279,23 +279,33 @@ static int bf5xx_pcm_mmap(struct snd_pcm_substream 
*substream,
return 0 ;
 }
 #else
-static int bf5xx_pcm_copy(struct snd_pcm_substream *substream, int channel,
-   snd_pcm_uframes_t pos,
-   void __user *buf, snd_pcm_uframes_t count)
+static int bf5xx_pcm_copy(struct snd_pcm_substream *substream,
+  int channel, unsigned long pos,
+  void *buf, unsigned long count)
 {
struct snd_pcm_runtime *runtime = substream->runtime;
unsigned int chan_mask = ac97_chan_mask[runtime->channels - 1];
+   struct ac97_frame *dst;
+
pr_debug("%s copy pos:0x%lx count:0x%lx\n",
substream->stream ? "Capture" : "Playback", pos, count);
+   dst = (struct ac97_frame *)runtime->dma_area +
+   bytes_to_frames(runtime, pos);
+   count = bytes_to_frames(runtime, count);
 
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
-   bf5xx_pcm_to_ac97((struct ac97_frame *)runtime->dma_area + pos,
-   (__u16 *)buf, count, chan_mask);
+   bf5xx_pcm_to_ac97(dst, buf, count, chan_mask);
else
-   bf5xx_ac97_to_pcm((struct ac97_frame *)runtime->dma_area + pos,
-   (__u16 *)buf, count);
+   bf5xx_ac97_to_pcm(dst, buf, count);
return 0;
 }
+
+static int bf5xx_pcm_copy_user(struct snd_pcm_substream *substream,
+   int channel, unsigned long pos,
+   void __user *buf, unsigned long count)
+{
+   return bf5xx_pcm_copy(substream, channel, pos, (void *)buf, count);
+}
 #endif
 
 static struct snd_pcm_ops bf5xx_pcm_ac97_ops = {
@@ -309,7 +319,8 @@ static struct snd_pcm_ops bf5xx_pcm_ac97_ops = {
 #if defined(CONFIG_SND_BF5XX_MMAP_SUPPORT)
.mmap   = bf5xx_pcm_mmap,
 #else
-   .copy   = bf5xx_pcm_copy,
+   .copy_user  = bf5xx_pcm_copy_user,
+   .copy_kernel= bf5xx_pcm_copy,
 #endif
 };
 
diff --git a/sound/soc/blackfin/bf5xx-i2s-pcm.c 
b/sound/soc/blackfin/bf5xx-i2s-pcm.c
index 6cba211da32e..470d99abf6f6 100644
--- a/sound/soc/blackfin/bf5xx-i2s-pcm.c
+++ b/sound/soc/blackfin/bf5xx-i2s-pcm.c
@@ -225,8 +225,9 @@ static int bf5xx_pcm_mmap(struct snd_pcm_substream 
*substream,
return 0 ;
 }
 
-static int bf5xx_pcm_copy(struct snd_pcm_substream *substream, int channel,
-   snd_pcm_uframes_t pos, void *buf, snd_pcm_uframes_t count)
+static int bf5xx_pcm_copy(struct snd_pcm_substream *substream,
+ int channel, unsigned long pos,
+ void *buf, unsigned long count)
 {
struct snd_soc_pcm_runtime *rtd = substream->private_data;
struct snd_pcm_runtime *runtime = substream->runtime;
@@ -238,6 +239,8 @@ static int bf5xx_pcm_copy(struct snd_pcm_substream 
*substream, int channel,
dma_data = snd_soc_dai_get_dma_data(rtd->cpu_dai, substream);
 
if (dma_data->tdm_mode) {
+   pos = bytes_to_frames(runtime, pos);
+   count = bytes_to_frames(runtime, count);
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
src = buf;
dst = runtime->dma_area;
@@ -269,21 +272,29 @@ static int bf5xx_pcm_copy(struct snd_pcm_substream 
*substream, int channel,
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
src = buf;
dst = runtime->dma_area;
-   dst += frames_to_bytes(runtime, pos);
+   dst += pos;
} else {
src = runtime->dma_area;
-   src += frames_to_bytes(runtime, pos);
+   src += pos;
dst = buf;
}
 
-   memcpy(dst, src, frames_to_bytes(runtime, count));
+   memcpy(dst, src, count);
}
 
return 0;
 }
 
+static int bf5xx_pcm_copy_user(struct snd_pcm_substream *substream,
+  int channel, unsigned long pos,
+  void __user *buf, unsigned long count)
+{
+   return bf5xx_pcm_copy(sub

[PATCH v2 00/27] Revised full patchset for PCM in-kernel copy support

2017-06-01 Thread Takashi Iwai
Hi,

this is a full patchset of what I sent previously, containing the all
changes instead of the snippet.  The main purpose of this patchset is
to eliminate the remaining usages of set_fs().  They are basically
used for in-kernel PCM data transfer, and this patch provides the new
API functions and replaces the hackish set_fs() calls with them.

Unlike the first patchset with the unified copy_silence ops, this adds
a new copy_kernel ops instead.  At the same time, copy/silence are
changed to receive the position and size in bytes instead of frames.
This allows us to simplify the PCM core code.  As a result, a good
amount of code could be removed from pcm_lib.c.

The difference from the previous patchset is that this is a full
patchset, i.e. all relevant drivers have been covered, and also some
small issues have been addressed, in addition, the documentation
update is provided, too.

I'm Cc'ing the media and the USB people since it touches solo6x10 and
usb-gadget drivers.

The previous ACK was dropped as each patch was rewritten again.  Sorry
for the doubly patch-review labours.


thanks,

Takashi

===

Takashi Iwai (26):
  ALSA: pcm: Introduce copy_user, copy_kernel and fill_silence ops
  ALSA: dummy: Convert to new PCM copy ops
  ALSA: es1938: Convert to the new PCM copy ops
  ALSA: nm256: Convert to new PCM copy ops
  ALSA: korg1212: Convert to the new PCM ops
  ALSA: rme32: Convert to the new PCM copy ops
  ALSA: rme96: Convert to the new PCM ops
  ALSA: rme9652: Convert to the new PCM ops
  ALSA: hdsp: Convert to the new PCM ops
  ALSA: gus: Convert to the new PCM ops
  ALSA: sb: Convert to the new PCM ops
  ALSA: sh: Convert to the new PCM ops
  ASoC: blackfin: Convert to the new PCM ops
  [media] solo6x10: Convert to the new PCM ops
  ALSA: pcm: Drop the old copy and silence ops
  ALSA: pcm: Check PCM state by a common helper function
  ALSA: pcm: Shuffle codes
  ALSA: pcm: Call directly the common read/write helpers
  ALSA: pcm: More unification of PCM transfer codes
  ALSA: pcm: Unify read/write loop
  ALSA: pcm: Simplify snd_pcm_playback_silence()
  ALSA: pcm: Direct in-kernel read/write support
  usb: gadget: u_uac1: Kill set_fs() usage
  ALSA: pcm: Kill set_fs() in PCM OSS layer
  ALSA: pcm: Build OSS writev/readv helpers conditionally
  ALSA: doc: Update copy_user, copy_kernel and fill_silence PCM ops

 .../sound/kernel-api/writing-an-alsa-driver.rst| 111 ++--
 drivers/media/pci/solo6x10/solo6x10-g723.c |  32 +-
 drivers/usb/gadget/function/u_uac1.c   |   7 +-
 include/sound/pcm.h|  80 ++-
 sound/core/oss/io.c|   4 +-
 sound/core/oss/pcm_oss.c   |  81 +--
 sound/core/oss/pcm_plugin.h|   6 +-
 sound/core/pcm_lib.c   | 564 -
 sound/drivers/dummy.c  |  20 +-
 sound/isa/gus/gus_pcm.c|  97 ++--
 sound/isa/sb/emu8000_pcm.c | 190 ---
 sound/pci/es1938.c |  33 +-
 sound/pci/korg1212/korg1212.c  | 112 ++--
 sound/pci/nm256/nm256.c|  57 ++-
 sound/pci/rme32.c  |  65 ++-
 sound/pci/rme96.c  |  70 ++-
 sound/pci/rme9652/hdsp.c   |  67 ++-
 sound/pci/rme9652/rme9652.c|  71 ++-
 sound/sh/sh_dac_audio.c|  54 +-
 sound/soc/blackfin/bf5xx-ac97-pcm.c|  27 +-
 sound/soc/blackfin/bf5xx-i2s-pcm.c |  36 +-
 sound/soc/soc-pcm.c|   5 +-
 22 files changed, 977 insertions(+), 812 deletions(-)

-- 
2.13.0



[PATCH v2 12/27] ALSA: sb: Convert to the new PCM ops

2017-06-01 Thread Takashi Iwai
Replace the copy and the silence ops with the new PCM ops.
For avoiding the code redundancy, slightly hackish macros are
introduced.

Signed-off-by: Takashi Iwai <ti...@suse.de>
---
 sound/isa/sb/emu8000_pcm.c | 190 ++---
 1 file changed, 109 insertions(+), 81 deletions(-)

diff --git a/sound/isa/sb/emu8000_pcm.c b/sound/isa/sb/emu8000_pcm.c
index c480024422af..2ee8d67871ec 100644
--- a/sound/isa/sb/emu8000_pcm.c
+++ b/sound/isa/sb/emu8000_pcm.c
@@ -422,121 +422,148 @@ do { \
return -EAGAIN;\
 } while (0)
 
+enum {
+   COPY_USER, COPY_KERNEL, FILL_SILENCE,
+};
+
+#define GET_VAL(sval, buf, mode)   \
+   do {\
+   switch (mode) { \
+   case FILL_SILENCE:  \
+   sval = 0;   \
+   break;  \
+   case COPY_KERNEL:   \
+   sval = *buf++;  \
+   break;  \
+   default:\
+   if (get_user(sval, (unsigned short __user *)buf)) \
+   return -EFAULT; \
+   buf++;  \
+   break;  \
+   }   \
+   } while (0)
 
 #ifdef USE_NONINTERLEAVE
-/* copy one channel block */
-static int emu8k_transfer_block(struct snd_emu8000 *emu, int offset, unsigned 
short *buf, int count)
-{
-   EMU8000_SMALW_WRITE(emu, offset);
-   while (count > 0) {
-   unsigned short sval;
-   CHECK_SCHEDULER();
-   if (get_user(sval, buf))
-   return -EFAULT;
-   EMU8000_SMLD_WRITE(emu, sval);
-   buf++;
-   count--;
-   }
-   return 0;
-}
 
+#define LOOP_WRITE(rec, offset, _buf, count, mode) \
+   do {\
+   struct snd_emu8000 *emu = (rec)->emu;   \
+   unsigned short *buf = (unsigned short *)(_buf); \
+   snd_emu8000_write_wait(emu, 1); \
+   EMU8000_SMALW_WRITE(emu, offset);   \
+   while (count > 0) { \
+   unsigned short sval;\
+   CHECK_SCHEDULER();  \
+   GET_VAL(sval, buf, mode);   \
+   EMU8000_SMLD_WRITE(emu, sval);  \
+   count--;\
+   }   \
+   } while (0)
+
+/* copy one channel block */
 static int emu8k_pcm_copy(struct snd_pcm_substream *subs,
- int voice,
- snd_pcm_uframes_t pos,
- void *src,
- snd_pcm_uframes_t count)
+ int voice, unsigned long pos,
+ void __user *src, unsigned long count)
 {
struct snd_emu8k_pcm *rec = subs->runtime->private_data;
-   struct snd_emu8000 *emu = rec->emu;
 
-   snd_emu8000_write_wait(emu, 1);
-   return emu8k_transfer_block(emu, pos + rec->loop_start[voice], src,
-   count);
+   /* convert to word unit */
+   pos = (pos << 1) + rec->loop_start[voice];
+   count <<= 1;
+   LOOP_WRITE(rec, pos, src, count, COPY_UESR);
+   return 0;
 }
 
-/* make a channel block silence */
-static int emu8k_silence_block(struct snd_emu8000 *emu, int offset, int count)
+static int emu8k_pcm_copy_kernel(struct snd_pcm_substream *subs,
+int voice, unsigned long pos,
+void *src, unsigned long count)
 {
-   EMU8000_SMALW_WRITE(emu, offset);
-   while (count > 0) {
-   CHECK_SCHEDULER();
-   EMU8000_SMLD_WRITE(emu, 0);
-   count--;
-   }
+   struct snd_emu8k_pcm *rec = subs->runtime->private_data;
+
+   /* convert to word unit */
+   pos = (pos << 1) + rec->loop_start[voice];
+   count <<= 1;
+   LOOP_WRITE(rec, pos, src, count, COPY_KERNEL);
return 0;
 }
 
+/* make a channel block silence */
 static int emu8k_pcm_silence(struct snd_pcm_substream *subs,
-int voice,
-snd_pcm_u

[PATCH v2 11/27] ALSA: gus: Convert to the new PCM ops

2017-06-01 Thread Takashi Iwai
Replace the copy and the silence ops with the new PCM ops.
For simplifying the code a bit, two local helpers are introduced here:
get_bpos() and playback_copy_ack().

Signed-off-by: Takashi Iwai <ti...@suse.de>
---
 sound/isa/gus/gus_pcm.c | 97 ++---
 1 file changed, 59 insertions(+), 38 deletions(-)

diff --git a/sound/isa/gus/gus_pcm.c b/sound/isa/gus/gus_pcm.c
index 0cc3f272edf1..b9f6dcbef889 100644
--- a/sound/isa/gus/gus_pcm.c
+++ b/sound/isa/gus/gus_pcm.c
@@ -353,26 +353,25 @@ static int snd_gf1_pcm_poke_block(struct snd_gus_card 
*gus, unsigned char *buf,
return 0;
 }
 
-static int snd_gf1_pcm_playback_copy(struct snd_pcm_substream *substream,
-int voice,
-snd_pcm_uframes_t pos,
-void __user *src,
-snd_pcm_uframes_t count)
+static int get_bpos(struct gus_pcm_private *pcmp, int voice, unsigned int pos,
+   unsigned int len)
 {
-   struct snd_pcm_runtime *runtime = substream->runtime;
-   struct gus_pcm_private *pcmp = runtime->private_data;
-   struct snd_gus_card *gus = pcmp->gus;
-   unsigned int bpos, len;
-   int w16, invert;
-   
-   bpos = samples_to_bytes(runtime, pos) + (voice * (pcmp->dma_size / 2));
-   len = samples_to_bytes(runtime, count);
+   unsigned int bpos = pos + (voice * (pcmp->dma_size / 2));
if (snd_BUG_ON(bpos > pcmp->dma_size))
return -EIO;
if (snd_BUG_ON(bpos + len > pcmp->dma_size))
return -EIO;
-   if (copy_from_user(runtime->dma_area + bpos, src, len))
-   return -EFAULT;
+   return bpos;
+}
+
+static int playback_copy_ack(struct snd_pcm_substream *substream,
+unsigned int bpos, unsigned int len)
+{
+   struct snd_pcm_runtime *runtime = substream->runtime;
+   struct gus_pcm_private *pcmp = runtime->private_data;
+   struct snd_gus_card *gus = pcmp->gus;
+   int w16, invert;
+
if (len > 32)
return snd_gf1_pcm_block_change(substream, bpos,
pcmp->memory + bpos, len);
@@ -383,33 +382,54 @@ static int snd_gf1_pcm_playback_copy(struct 
snd_pcm_substream *substream,
  pcmp->memory + bpos, len, w16, invert);
 }
 
+static int snd_gf1_pcm_playback_copy(struct snd_pcm_substream *substream,
+int voice, unsigned long pos,
+void __user *src, unsigned long count)
+{
+   struct snd_pcm_runtime *runtime = substream->runtime;
+   struct gus_pcm_private *pcmp = runtime->private_data;
+   unsigned int len = count;
+   int bpos;
+
+   bpos = get_bpos(pcmp, voice, pos, len);
+   if (bpos < 0)
+   return pos;
+   if (copy_from_user(runtime->dma_area + bpos, src, len))
+   return -EFAULT;
+   return playback_copy_ack(substream, bpos, len);
+}
+
+static int snd_gf1_pcm_playback_copy_kernel(struct snd_pcm_substream 
*substream,
+   int voice, unsigned long pos,
+   void *src, unsigned long count)
+{
+   struct snd_pcm_runtime *runtime = substream->runtime;
+   struct gus_pcm_private *pcmp = runtime->private_data;
+   unsigned int len = count;
+   int bpos;
+
+   bpos = get_bpos(pcmp, voice, pos, len);
+   if (bpos < 0)
+   return pos;
+   memcpy(runtime->dma_area + bpos, src, len);
+   return playback_copy_ack(substream, bpos, len);
+}
+
 static int snd_gf1_pcm_playback_silence(struct snd_pcm_substream *substream,
-   int voice,
-   snd_pcm_uframes_t pos,
-   snd_pcm_uframes_t count)
+   int voice, unsigned long pos,
+   unsigned long count)
 {
struct snd_pcm_runtime *runtime = substream->runtime;
struct gus_pcm_private *pcmp = runtime->private_data;
-   struct snd_gus_card *gus = pcmp->gus;
-   unsigned int bpos, len;
-   int w16, invert;
+   unsigned int len = count;
+   int bpos;

-   bpos = samples_to_bytes(runtime, pos) + (voice * (pcmp->dma_size / 2));
-   len = samples_to_bytes(runtime, count);
-   if (snd_BUG_ON(bpos > pcmp->dma_size))
-   return -EIO;
-   if (snd_BUG_ON(bpos + len > pcmp->dma_size))
-   return -EIO;
+   bpos = get_bpos(pcmp, voice, pos, len);
+   if (bpos < 0)
+   return pos;
snd_pcm_format_set_silence(runtime->format, runtime->dma_area + bpos,
-

[PATCH v2 13/27] ALSA: sh: Convert to the new PCM ops

2017-06-01 Thread Takashi Iwai
Replace the copy and the silence ops with the new PCM ops.
Fixed also the user-space buffer copy with the proper
copy_from_user*() variant.

Signed-off-by: Takashi Iwai <ti...@suse.de>
---
 sound/sh/sh_dac_audio.c | 54 +++--
 1 file changed, 30 insertions(+), 24 deletions(-)

diff --git a/sound/sh/sh_dac_audio.c b/sound/sh/sh_dac_audio.c
index 461b310c7872..c1e00ed715ee 100644
--- a/sound/sh/sh_dac_audio.c
+++ b/sound/sh/sh_dac_audio.c
@@ -184,23 +184,36 @@ static int snd_sh_dac_pcm_trigger(struct 
snd_pcm_substream *substream, int cmd)
return 0;
 }
 
-static int snd_sh_dac_pcm_copy(struct snd_pcm_substream *substream, int 
channel,
-   snd_pcm_uframes_t pos, void __user *src, snd_pcm_uframes_t count)
+static int snd_sh_dac_pcm_copy(struct snd_pcm_substream *substream,
+  int channel, unsigned long pos,
+  void __user *src, unsigned long count)
 {
/* channel is not used (interleaved data) */
struct snd_sh_dac *chip = snd_pcm_substream_chip(substream);
struct snd_pcm_runtime *runtime = substream->runtime;
-   ssize_t b_count = frames_to_bytes(runtime , count);
-   ssize_t b_pos = frames_to_bytes(runtime , pos);
 
-   if (count < 0)
-   return -EINVAL;
+   if (copy_from_user_toio(chip->data_buffer + pos, src, count))
+   return -EFAULT;
+   chip->buffer_end = chip->data_buffer + pos + count;
 
-   if (!count)
-   return 0;
+   if (chip->empty) {
+   chip->empty = 0;
+   dac_audio_start_timer(chip);
+   }
+
+   return 0;
+}
 
-   memcpy_toio(chip->data_buffer + b_pos, src, b_count);
-   chip->buffer_end = chip->data_buffer + b_pos + b_count;
+static int snd_sh_dac_pcm_copy_kernel(struct snd_pcm_substream *substream,
+ int channel, unsigned long pos,
+ void *src, unsigned long count)
+{
+   /* channel is not used (interleaved data) */
+   struct snd_sh_dac *chip = snd_pcm_substream_chip(substream);
+   struct snd_pcm_runtime *runtime = substream->runtime;
+
+   memcpy_toio(chip->data_buffer + pos, src, count);
+   chip->buffer_end = chip->data_buffer + pos + count;
 
if (chip->empty) {
chip->empty = 0;
@@ -211,23 +224,15 @@ static int snd_sh_dac_pcm_copy(struct snd_pcm_substream 
*substream, int channel,
 }
 
 static int snd_sh_dac_pcm_silence(struct snd_pcm_substream *substream,
- int channel, snd_pcm_uframes_t pos,
- snd_pcm_uframes_t count)
+ int channel, unsigned long pos,
+ unsigned long count)
 {
/* channel is not used (interleaved data) */
struct snd_sh_dac *chip = snd_pcm_substream_chip(substream);
struct snd_pcm_runtime *runtime = substream->runtime;
-   ssize_t b_count = frames_to_bytes(runtime , count);
-   ssize_t b_pos = frames_to_bytes(runtime , pos);
-
-   if (count < 0)
-   return -EINVAL;
-
-   if (!count)
-   return 0;
 
-   memset_io(chip->data_buffer + b_pos, 0, b_count);
-   chip->buffer_end = chip->data_buffer + b_pos + b_count;
+   memset_io(chip->data_buffer + pos, 0, count);
+   chip->buffer_end = chip->data_buffer + pos + count;
 
if (chip->empty) {
chip->empty = 0;
@@ -256,8 +261,9 @@ static struct snd_pcm_ops snd_sh_dac_pcm_ops = {
.prepare= snd_sh_dac_pcm_prepare,
.trigger= snd_sh_dac_pcm_trigger,
.pointer= snd_sh_dac_pcm_pointer,
-   .copy   = snd_sh_dac_pcm_copy,
-   .silence= snd_sh_dac_pcm_silence,
+   .copy_user  = snd_sh_dac_pcm_copy,
+   .copy_kernel= snd_sh_dac_pcm_copy_kernel,
+   .fill_silence   = snd_sh_dac_pcm_silence,
.mmap   = snd_pcm_lib_mmap_iomem,
 };
 
-- 
2.13.0



[PATCH v2 24/27] usb: gadget: u_uac1: Kill set_fs() usage

2017-06-01 Thread Takashi Iwai
With the new API to perform the in-kernel buffer copy, we can get rid
of set_fs() usage in this driver, finally.

Signed-off-by: Takashi Iwai <ti...@suse.de>
---
 drivers/usb/gadget/function/u_uac1.c | 7 +--
 1 file changed, 1 insertion(+), 6 deletions(-)

diff --git a/drivers/usb/gadget/function/u_uac1.c 
b/drivers/usb/gadget/function/u_uac1.c
index c78c84138a28..ca88e4c0fd1e 100644
--- a/drivers/usb/gadget/function/u_uac1.c
+++ b/drivers/usb/gadget/function/u_uac1.c
@@ -157,7 +157,6 @@ size_t u_audio_playback(struct gaudio *card, void *buf, 
size_t count)
struct gaudio_snd_dev   *snd = >playback;
struct snd_pcm_substream *substream = snd->substream;
struct snd_pcm_runtime *runtime = substream->runtime;
-   mm_segment_t old_fs;
ssize_t result;
snd_pcm_sframes_t frames;
 
@@ -174,15 +173,11 @@ size_t u_audio_playback(struct gaudio *card, void *buf, 
size_t count)
}
 
frames = bytes_to_frames(runtime, count);
-   old_fs = get_fs();
-   set_fs(KERNEL_DS);
-   result = snd_pcm_lib_write(snd->substream, (void __user *)buf, frames);
+   result = snd_pcm_kernel_write(snd->substream, buf, frames);
if (result != frames) {
ERROR(card, "Playback error: %d\n", (int)result);
-   set_fs(old_fs);
goto try_again;
}
-   set_fs(old_fs);
 
return 0;
 }
-- 
2.13.0



[PATCH v2 05/27] ALSA: nm256: Convert to new PCM copy ops

2017-06-01 Thread Takashi Iwai
Replace the copy and the silence ops with the new ops.
The conversion is straightforward with standard helper functions, and
now we can drop the bytes <-> frames conversions in callbacks.

Signed-off-by: Takashi Iwai <ti...@suse.de>
---
 sound/pci/nm256/nm256.c | 57 -
 1 file changed, 37 insertions(+), 20 deletions(-)

diff --git a/sound/pci/nm256/nm256.c b/sound/pci/nm256/nm256.c
index 103fe311e5a9..63f0985dae27 100644
--- a/sound/pci/nm256/nm256.c
+++ b/sound/pci/nm256/nm256.c
@@ -695,53 +695,68 @@ snd_nm256_capture_pointer(struct snd_pcm_substream 
*substream)
  */
 static int
 snd_nm256_playback_silence(struct snd_pcm_substream *substream,
-  int channel, /* not used (interleaved data) */
-  snd_pcm_uframes_t pos,
-  snd_pcm_uframes_t count)
+  int channel, unsigned long pos, unsigned long count)
 {
struct snd_pcm_runtime *runtime = substream->runtime;
struct nm256_stream *s = runtime->private_data;
-   count = frames_to_bytes(runtime, count);
-   pos = frames_to_bytes(runtime, pos);
+
memset_io(s->bufptr + pos, 0, count);
return 0;
 }
 
 static int
 snd_nm256_playback_copy(struct snd_pcm_substream *substream,
-   int channel, /* not used (interleaved data) */
-   snd_pcm_uframes_t pos,
-   void __user *src,
-   snd_pcm_uframes_t count)
+   int channel, unsigned long pos,
+   void __user *src, unsigned long count)
 {
struct snd_pcm_runtime *runtime = substream->runtime;
struct nm256_stream *s = runtime->private_data;
-   count = frames_to_bytes(runtime, count);
-   pos = frames_to_bytes(runtime, pos);
+
if (copy_from_user_toio(s->bufptr + pos, src, count))
return -EFAULT;
return 0;
 }
 
+static int
+snd_nm256_playback_copy_kernel(struct snd_pcm_substream *substream,
+  int channel, unsigned long pos,
+  void *src, unsigned long count)
+{
+   struct snd_pcm_runtime *runtime = substream->runtime;
+   struct nm256_stream *s = runtime->private_data;
+
+   memcpy_toio(s->bufptr + pos, src, count);
+   return 0;
+}
+
 /*
  * copy to user
  */
 static int
 snd_nm256_capture_copy(struct snd_pcm_substream *substream,
-  int channel, /* not used (interleaved data) */
-  snd_pcm_uframes_t pos,
-  void __user *dst,
-  snd_pcm_uframes_t count)
+  int channel, unsigned long pos,
+  void __user *dst, unsigned long count)
 {
struct snd_pcm_runtime *runtime = substream->runtime;
struct nm256_stream *s = runtime->private_data;
-   count = frames_to_bytes(runtime, count);
-   pos = frames_to_bytes(runtime, pos);
+
if (copy_to_user_fromio(dst, s->bufptr + pos, count))
return -EFAULT;
return 0;
 }
 
+static int
+snd_nm256_capture_copy_kernel(struct snd_pcm_substream *substream,
+ int channel, unsigned long pos,
+ void *dst, unsigned long count)
+{
+   struct snd_pcm_runtime *runtime = substream->runtime;
+   struct nm256_stream *s = runtime->private_data;
+
+   memcpy_fromio(dst, s->bufptr + pos, count);
+   return 0;
+}
+
 #endif /* !__i386__ */
 
 
@@ -911,8 +926,9 @@ static const struct snd_pcm_ops snd_nm256_playback_ops = {
.trigger =  snd_nm256_playback_trigger,
.pointer =  snd_nm256_playback_pointer,
 #ifndef __i386__
-   .copy = snd_nm256_playback_copy,
-   .silence =  snd_nm256_playback_silence,
+   .copy_user =snd_nm256_playback_copy,
+   .copy_kernel =  snd_nm256_playback_copy_kernel,
+   .fill_silence = snd_nm256_playback_silence,
 #endif
.mmap = snd_pcm_lib_mmap_iomem,
 };
@@ -926,7 +942,8 @@ static const struct snd_pcm_ops snd_nm256_capture_ops = {
.trigger =  snd_nm256_capture_trigger,
.pointer =  snd_nm256_capture_pointer,
 #ifndef __i386__
-   .copy = snd_nm256_capture_copy,
+   .copy_user =snd_nm256_capture_copy,
+   .copy_kernel =  snd_nm256_capture_copy_kernel,
 #endif
.mmap = snd_pcm_lib_mmap_iomem,
 };
-- 
2.13.0



[PATCH v2 20/27] ALSA: pcm: More unification of PCM transfer codes

2017-06-01 Thread Takashi Iwai
This patch proceeds more abstraction of PCM read/write loop codes.

For both interleaved and non-interleaved transfers, the same copy or
silence transfer code (which is defined as pcm_transfer_f) is used
now.  This became possible since we switched to byte size to copy_*
and fill_silence ops argument instead of frames.

And, for both read and write, we can use the same copy function (which
is defined as pcm_copy_f), just depending on whether interleaved or
non-interleaved mode.

The transfer function is determined at the beginning of the loop,
depending on whether the driver gives the specific copy ops or it's
the standard read/write.

Another bonus by this change is that we now guarantee the silencing
behavior when NULL buffer is passed to write helpers.  It'll simplify
some codes later.

Signed-off-by: Takashi Iwai <ti...@suse.de>
---
 sound/core/pcm_lib.c | 254 +--
 1 file changed, 123 insertions(+), 131 deletions(-)

diff --git a/sound/core/pcm_lib.c b/sound/core/pcm_lib.c
index 1bd7244324d5..eb9cbc2d9d7b 100644
--- a/sound/core/pcm_lib.c
+++ b/sound/core/pcm_lib.c
@@ -1991,77 +1991,100 @@ static int wait_for_avail(struct snd_pcm_substream 
*substream,
return err;
 }

-typedef int (*transfer_f)(struct snd_pcm_substream *substream, unsigned int 
hwoff,
- void  *data, unsigned int off,
- snd_pcm_uframes_t size);
+typedef int (*pcm_transfer_f)(struct snd_pcm_substream *substream,
+ int channel, unsigned long hwoff,
+ void *buf, unsigned long bytes);
 
-static int snd_pcm_lib_write_transfer(struct snd_pcm_substream *substream,
- unsigned int hwoff,
- void *data, unsigned int off,
- snd_pcm_uframes_t frames)
+typedef int (*pcm_copy_f)(struct snd_pcm_substream *, snd_pcm_uframes_t, void 
*,
+ snd_pcm_uframes_t, snd_pcm_uframes_t, pcm_transfer_f);
+
+/* calculate the target DMA-buffer position to be written/read */
+static void *get_dma_ptr(struct snd_pcm_runtime *runtime,
+  int channel, unsigned long hwoff)
+{
+   return runtime->dma_area + hwoff +
+   channel * (runtime->dma_bytes / runtime->channels);
+}
+
+/* default copy_user ops for write */
+static int default_write_copy_user(struct snd_pcm_substream *substream,
+  int channel, unsigned long hwoff,
+  void __user *buf, unsigned long bytes)
+{
+   if (copy_from_user(get_dma_ptr(substream->runtime, channel, hwoff),
+  buf, bytes))
+   return -EFAULT;
+   return 0;
+}
+
+/* fill silence instead of copy data; called as a transfer helper
+ * from __snd_pcm_lib_write() or directly from noninterleaved_copy() when
+ * a NULL buffer is passed
+ */
+static int fill_silence(struct snd_pcm_substream *substream, int channel,
+   unsigned long hwoff, void *buf, unsigned long bytes)
 {
struct snd_pcm_runtime *runtime = substream->runtime;
-   int err;
-   char __user *buf = (char __user *) data + frames_to_bytes(runtime, off);
-   if (substream->ops->copy_user) {
-   hwoff = frames_to_bytes(runtime, hwoff);
-   frames = frames_to_bytes(runtime, frames);
-   err = substream->ops->copy_user(substream, 0, hwoff, buf, 
frames);
-   if (err < 0)
-   return err;
-   } else {
-   char *hwbuf = runtime->dma_area + frames_to_bytes(runtime, 
hwoff);
-   if (copy_from_user(hwbuf, buf, frames_to_bytes(runtime, 
frames)))
-   return -EFAULT;
-   }
+
+   if (substream->stream != SNDRV_PCM_STREAM_PLAYBACK)
+   return 0;
+   if (substream->ops->fill_silence)
+   return substream->ops->fill_silence(substream, channel,
+   hwoff, bytes);
+
+   snd_pcm_format_set_silence(runtime->format,
+  get_dma_ptr(runtime, channel, hwoff),
+  bytes_to_samples(runtime, bytes));
return 0;
 }
- 
-static int snd_pcm_lib_writev_transfer(struct snd_pcm_substream *substream,
-  unsigned int hwoff,
-  void *data, unsigned int off,
-  snd_pcm_uframes_t frames)
+
+/* call transfer function with the converted pointers and sizes;
+ * for interleaved mode, it's one shot for all samples
+ */
+static int interleaved_copy(struct snd_pcm_substream *substream,
+   snd_pcm_uframes_t hwoff, void *data,
+   snd_pcm_uframes_t 

[PATCH v2 18/27] ALSA: pcm: Shuffle codes

2017-06-01 Thread Takashi Iwai
Just shuffle the codes, without any change otherwise.

Signed-off-by: Takashi Iwai <ti...@suse.de>
---
 sound/core/pcm_lib.c | 212 +--
 1 file changed, 106 insertions(+), 106 deletions(-)

diff --git a/sound/core/pcm_lib.c b/sound/core/pcm_lib.c
index e4f5c43b6448..1f5251cca607 100644
--- a/sound/core/pcm_lib.c
+++ b/sound/core/pcm_lib.c
@@ -1991,6 +1991,10 @@ static int wait_for_avail(struct snd_pcm_substream 
*substream,
return err;
 }

+typedef int (*transfer_f)(struct snd_pcm_substream *substream, unsigned int 
hwoff,
+ unsigned long data, unsigned int off,
+ snd_pcm_uframes_t size);
+
 static int snd_pcm_lib_write_transfer(struct snd_pcm_substream *substream,
  unsigned int hwoff,
  unsigned long data, unsigned int off,
@@ -2013,9 +2017,68 @@ static int snd_pcm_lib_write_transfer(struct 
snd_pcm_substream *substream,
return 0;
 }
  
-typedef int (*transfer_f)(struct snd_pcm_substream *substream, unsigned int 
hwoff,
- unsigned long data, unsigned int off,
- snd_pcm_uframes_t size);
+static int snd_pcm_lib_writev_transfer(struct snd_pcm_substream *substream,
+  unsigned int hwoff,
+  unsigned long data, unsigned int off,
+  snd_pcm_uframes_t frames)
+{
+   struct snd_pcm_runtime *runtime = substream->runtime;
+   int err;
+   void __user **bufs = (void __user **)data;
+   int channels = runtime->channels;
+   char __user *buf;
+   int c;
+
+   if (substream->ops->copy_user) {
+   hwoff = samples_to_bytes(runtime, hwoff);
+   off = samples_to_bytes(runtime, off);
+   frames = samples_to_bytes(runtime, frames);
+   for (c = 0; c < channels; ++c, ++bufs) {
+   buf = *bufs + off;
+   if (!*bufs) {
+   if (snd_BUG_ON(!substream->ops->fill_silence))
+   return -EINVAL;
+   err = substream->ops->fill_silence(substream, c,
+  hwoff,
+  frames);
+   } else {
+   err = substream->ops->copy_user(substream, c,
+   hwoff, buf,
+   frames);
+   }
+   if (err < 0)
+   return err;
+   }
+   } else {
+   /* default transfer behaviour */
+   size_t dma_csize = runtime->dma_bytes / channels;
+   for (c = 0; c < channels; ++c, ++bufs) {
+   char *hwbuf = runtime->dma_area + (c * dma_csize) + 
samples_to_bytes(runtime, hwoff);
+   if (*bufs == NULL) {
+   snd_pcm_format_set_silence(runtime->format, 
hwbuf, frames);
+   } else {
+   char __user *buf = *bufs + 
samples_to_bytes(runtime, off);
+   if (copy_from_user(hwbuf, buf, 
samples_to_bytes(runtime, frames)))
+   return -EFAULT;
+   }
+   }
+   }
+   return 0;
+}
+
+/* sanity-check for read/write methods */
+static int pcm_sanity_check(struct snd_pcm_substream *substream)
+{
+   struct snd_pcm_runtime *runtime;
+   if (PCM_RUNTIME_CHECK(substream))
+   return -ENXIO;
+   runtime = substream->runtime;
+   if (snd_BUG_ON(!substream->ops->copy_user && !runtime->dma_area))
+   return -EINVAL;
+   if (runtime->status->state == SNDRV_PCM_STATE_OPEN)
+   return -EBADFD;
+   return 0;
+}
 
 static int pcm_accessible_state(struct snd_pcm_runtime *runtime)
 {
@@ -2116,20 +2179,6 @@ static snd_pcm_sframes_t snd_pcm_lib_write1(struct 
snd_pcm_substream *substream,
return xfer > 0 ? (snd_pcm_sframes_t)xfer : err;
 }
 
-/* sanity-check for read/write methods */
-static int pcm_sanity_check(struct snd_pcm_substream *substream)
-{
-   struct snd_pcm_runtime *runtime;
-   if (PCM_RUNTIME_CHECK(substream))
-   return -ENXIO;
-   runtime = substream->runtime;
-   if (snd_BUG_ON(!substream->ops->copy_user && !runtime->dma_area))
-   return -EINVAL;
-   if (runtime->status->state == SNDRV_PCM_STATE_OPEN)
-   return -EBADFD;
-   return 0;
-}
-
 snd_pcm_sframes_t snd_pcm_lib_write(struct snd

[PATCH v2 27/27] ALSA: doc: Update copy_user, copy_kernel and fill_silence PCM ops

2017-06-01 Thread Takashi Iwai
Signed-off-by: Takashi Iwai <ti...@suse.de>
---
 .../sound/kernel-api/writing-an-alsa-driver.rst| 111 ++---
 1 file changed, 76 insertions(+), 35 deletions(-)

diff --git a/Documentation/sound/kernel-api/writing-an-alsa-driver.rst 
b/Documentation/sound/kernel-api/writing-an-alsa-driver.rst
index 95c5443eff38..58ffa3f5bda7 100644
--- a/Documentation/sound/kernel-api/writing-an-alsa-driver.rst
+++ b/Documentation/sound/kernel-api/writing-an-alsa-driver.rst
@@ -2080,8 +2080,8 @@ sleeping poll threads, etc.
 
 This callback is also atomic as default.
 
-copy and silence callbacks
-~~
+copy_user, copy_kernel and fill_silence ops
+~~~
 
 These callbacks are not mandatory, and can be omitted in most cases.
 These callbacks are used when the hardware buffer cannot be in the
@@ -3532,8 +3532,9 @@ external hardware buffer in interrupts (or in tasklets, 
preferably).
 
 The first case works fine if the external hardware buffer is large
 enough. This method doesn't need any extra buffers and thus is more
-effective. You need to define the ``copy`` and ``silence`` callbacks
-for the data transfer. However, there is a drawback: it cannot be
+effective. You need to define the ``copy_user`` and ``copy_kernel``
+callbacks for the data transfer, in addition to ``fill_silence``
+callback for playback. However, there is a drawback: it cannot be
 mmapped. The examples are GUS's GF1 PCM or emu8000's wavetable PCM.
 
 The second case allows for mmap on the buffer, although you have to
@@ -3545,30 +3546,34 @@ Another case is when the chip uses a PCI memory-map 
region for the
 buffer instead of the host memory. In this case, mmap is available only
 on certain architectures like the Intel one. In non-mmap mode, the data
 cannot be transferred as in the normal way. Thus you need to define the
-``copy`` and ``silence`` callbacks as well, as in the cases above. The
-examples are found in ``rme32.c`` and ``rme96.c``.
+``copy_user``, ``copy_kernel`` and ``fill_silence`` callbacks as well,
+as in the cases above. The examples are found in ``rme32.c`` and
+``rme96.c``.
 
-The implementation of the ``copy`` and ``silence`` callbacks depends
-upon whether the hardware supports interleaved or non-interleaved
-samples. The ``copy`` callback is defined like below, a bit
-differently depending whether the direction is playback or capture:
+The implementation of the ``copy_user``, ``copy_kernel`` and
+``silence`` callbacks depends upon whether the hardware supports
+interleaved or non-interleaved samples. The ``copy_user`` callback is
+defined like below, a bit differently depending whether the direction
+is playback or capture:
 
 ::
 
-  static int playback_copy(struct snd_pcm_substream *substream, int channel,
-   snd_pcm_uframes_t pos, void *src, snd_pcm_uframes_t count);
-  static int capture_copy(struct snd_pcm_substream *substream, int channel,
-   snd_pcm_uframes_t pos, void *dst, snd_pcm_uframes_t count);
+  static int playback_copy_user(struct snd_pcm_substream *substream,
+   int channel, unsigned long pos,
+   void __user *src, unsigned long count);
+  static int capture_copy_user(struct snd_pcm_substream *substream,
+   int channel, unsigned long pos,
+   void __user *dst, unsigned long count);
 
 In the case of interleaved samples, the second argument (``channel``) is
 not used. The third argument (``pos``) points the current position
-offset in frames.
+offset in bytes.
 
 The meaning of the fourth argument is different between playback and
 capture. For playback, it holds the source data pointer, and for
 capture, it's the destination data pointer.
 
-The last argument is the number of frames to be copied.
+The last argument is the number of bytes to be copied.
 
 What you have to do in this callback is again different between playback
 and capture directions. In the playback case, you copy the given amount
@@ -3578,8 +3583,7 @@ way, the copy would be like:
 
 ::
 
-  my_memcpy(my_buffer + frames_to_bytes(runtime, pos), src,
-frames_to_bytes(runtime, count));
+  my_memcpy_from_user(my_buffer + pos, src, count);
 
 For the capture direction, you copy the given amount of data (``count``)
 at the specified offset (``pos``) on the hardware buffer to the
@@ -3587,31 +3591,68 @@ specified pointer (``dst``).
 
 ::
 
-  my_memcpy(dst, my_buffer + frames_to_bytes(runtime, pos),
-frames_to_bytes(runtime, count));
+  my_memcpy_to_user(dst, my_buffer + pos, count);
+
+Here the functions are named as ``from_user`` and ``to_user`` because
+it's the user-space buffer that is passed to these callbacks.  That
+is, the callback is supposed to copy from/to the user-space data
+directly to/from the hardware buffer.
 
-Note that both the position and the amount of data are given in frames.
+Careful readers might notice that these callbacks receive the
+arguments in

[PATCH v2 22/27] ALSA: pcm: Simplify snd_pcm_playback_silence()

2017-06-01 Thread Takashi Iwai
Use the existing silence helper codes for simplification.

Signed-off-by: Takashi Iwai <ti...@suse.de>
---
 sound/core/pcm_lib.c | 50 --
 1 file changed, 20 insertions(+), 30 deletions(-)

diff --git a/sound/core/pcm_lib.c b/sound/core/pcm_lib.c
index f15460eaf8b5..a592d3308474 100644
--- a/sound/core/pcm_lib.c
+++ b/sound/core/pcm_lib.c
@@ -42,6 +42,9 @@
 #define trace_hw_ptr_error(substream, reason)
 #endif
 
+static int fill_silence_frames(struct snd_pcm_substream *substream,
+  snd_pcm_uframes_t off, snd_pcm_uframes_t frames);
+
 /*
  * fill ring buffer with silence
  * runtime->silence_start: starting pointer to silence area
@@ -55,7 +58,6 @@ void snd_pcm_playback_silence(struct snd_pcm_substream 
*substream, snd_pcm_ufram
 {
struct snd_pcm_runtime *runtime = substream->runtime;
snd_pcm_uframes_t frames, ofs, transfer;
-   char *hwbuf;
int err;
 
if (runtime->silence_size < runtime->boundary) {
@@ -109,35 +111,8 @@ void snd_pcm_playback_silence(struct snd_pcm_substream 
*substream, snd_pcm_ufram
ofs = runtime->silence_start % runtime->buffer_size;
while (frames > 0) {
transfer = ofs + frames > runtime->buffer_size ? 
runtime->buffer_size - ofs : frames;
-   if (runtime->access == SNDRV_PCM_ACCESS_RW_INTERLEAVED ||
-   runtime->access == SNDRV_PCM_ACCESS_MMAP_INTERLEAVED) {
-   if (substream->ops->fill_silence) {
-   err = substream->ops->fill_silence(substream, 0,
-  
frames_to_bytes(runtime, ofs),
-  
frames_to_bytes(runtime, transfer));
-   snd_BUG_ON(err < 0);
-   } else {
-   hwbuf = runtime->dma_area + 
frames_to_bytes(runtime, ofs);
-   snd_pcm_format_set_silence(runtime->format, 
hwbuf, transfer * runtime->channels);
-   }
-   } else {
-   unsigned int c;
-   unsigned int channels = runtime->channels;
-   if (substream->ops->fill_silence) {
-   for (c = 0; c < channels; ++c) {
-   err = 
substream->ops->fill_silence(substream, c,
-  
samples_to_bytes(runtime, ofs),
-  
samples_to_bytes(runtime, transfer));
-   snd_BUG_ON(err < 0);
-   }
-   } else {
-   size_t dma_csize = runtime->dma_bytes / 
channels;
-   for (c = 0; c < channels; ++c) {
-   hwbuf = runtime->dma_area + (c * 
dma_csize) + samples_to_bytes(runtime, ofs);
-   
snd_pcm_format_set_silence(runtime->format, hwbuf, transfer);
-   }
-   }
-   }
+   err = fill_silence_frames(substream, ofs, transfer);
+   snd_BUG_ON(err < 0);
runtime->silence_filled += transfer;
frames -= transfer;
ofs = 0;
@@ -2101,6 +2076,21 @@ static int noninterleaved_copy(struct snd_pcm_substream 
*substream,
return 0;
 }
 
+/* fill silence on the given buffer position;
+ * called from snd_pcm_playback_silence()
+ */
+static int fill_silence_frames(struct snd_pcm_substream *substream,
+  snd_pcm_uframes_t off, snd_pcm_uframes_t frames)
+{
+   if (substream->runtime->access == SNDRV_PCM_ACCESS_RW_INTERLEAVED ||
+   substream->runtime->access == SNDRV_PCM_ACCESS_MMAP_INTERLEAVED)
+   return interleaved_copy(substream, off, NULL, 0, frames,
+   fill_silence);
+   else
+   return noninterleaved_copy(substream, off, NULL, 0, frames,
+  fill_silence);
+}
+
 /* sanity-check for read/write methods */
 static int pcm_sanity_check(struct snd_pcm_substream *substream)
 {
-- 
2.13.0



[PATCH v2 25/27] ALSA: pcm: Kill set_fs() in PCM OSS layer

2017-06-01 Thread Takashi Iwai
This is the last-standing one: kill the set_fs() usage in PCM OSS
layer by replacing with the new API functions to deal with the direct
in-kernel buffer copying.

The code to fill the silence can be replaced even to a one-liner to
pass NULL buffer instead of the manual copying.

Signed-off-by: Takashi Iwai <ti...@suse.de>
---
 sound/core/oss/pcm_oss.c | 77 
 1 file changed, 12 insertions(+), 65 deletions(-)

diff --git a/sound/core/oss/pcm_oss.c b/sound/core/oss/pcm_oss.c
index e306f05ce51d..2d6a825cfe88 100644
--- a/sound/core/oss/pcm_oss.c
+++ b/sound/core/oss/pcm_oss.c
@@ -67,18 +67,6 @@ static int snd_pcm_oss_get_rate(struct snd_pcm_oss_file 
*pcm_oss_file);
 static int snd_pcm_oss_get_channels(struct snd_pcm_oss_file *pcm_oss_file);
 static int snd_pcm_oss_get_format(struct snd_pcm_oss_file *pcm_oss_file);
 
-static inline mm_segment_t snd_enter_user(void)
-{
-   mm_segment_t fs = get_fs();
-   set_fs(get_ds());
-   return fs;
-}
-
-static inline void snd_leave_user(mm_segment_t fs)
-{
-   set_fs(fs);
-}
-
 /*
  * helper functions to process hw_params
  */
@@ -1191,14 +1179,8 @@ snd_pcm_sframes_t snd_pcm_oss_write3(struct 
snd_pcm_substream *substream, const
if (ret < 0)
break;
}
-   if (in_kernel) {
-   mm_segment_t fs;
-   fs = snd_enter_user();
-   ret = snd_pcm_lib_write(substream, (void __force __user 
*)ptr, frames);
-   snd_leave_user(fs);
-   } else {
-   ret = snd_pcm_lib_write(substream, (void __force __user 
*)ptr, frames);
-   }
+   ret = __snd_pcm_lib_xfer(substream, (void *)ptr, true,
+frames, in_kernel);
if (ret != -EPIPE && ret != -ESTRPIPE)
break;
/* test, if we can't store new data, because the stream */
@@ -1234,14 +1216,8 @@ snd_pcm_sframes_t snd_pcm_oss_read3(struct 
snd_pcm_substream *substream, char *p
ret = snd_pcm_oss_capture_position_fixup(substream, );
if (ret < 0)
break;
-   if (in_kernel) {
-   mm_segment_t fs;
-   fs = snd_enter_user();
-   ret = snd_pcm_lib_read(substream, (void __force __user 
*)ptr, frames);
-   snd_leave_user(fs);
-   } else {
-   ret = snd_pcm_lib_read(substream, (void __force __user 
*)ptr, frames);
-   }
+   ret = __snd_pcm_lib_xfer(substream, (void *)ptr, true,
+frames, in_kernel);
if (ret == -EPIPE) {
if (runtime->status->state == SNDRV_PCM_STATE_DRAINING) 
{
ret = snd_pcm_kernel_ioctl(substream, 
SNDRV_PCM_IOCTL_DROP, NULL);
@@ -1273,14 +1249,8 @@ snd_pcm_sframes_t snd_pcm_oss_writev3(struct 
snd_pcm_substream *substream, void
if (ret < 0)
break;
}
-   if (in_kernel) {
-   mm_segment_t fs;
-   fs = snd_enter_user();
-   ret = snd_pcm_lib_writev(substream, (void __user 
**)bufs, frames);
-   snd_leave_user(fs);
-   } else {
-   ret = snd_pcm_lib_writev(substream, (void __user 
**)bufs, frames);
-   }
+   ret = __snd_pcm_lib_xfer(substream, bufs, false, frames,
+in_kernel);
if (ret != -EPIPE && ret != -ESTRPIPE)
break;
 
@@ -1313,14 +1283,8 @@ snd_pcm_sframes_t snd_pcm_oss_readv3(struct 
snd_pcm_substream *substream, void *
if (ret < 0)
break;
}
-   if (in_kernel) {
-   mm_segment_t fs;
-   fs = snd_enter_user();
-   ret = snd_pcm_lib_readv(substream, (void __user 
**)bufs, frames);
-   snd_leave_user(fs);
-   } else {
-   ret = snd_pcm_lib_readv(substream, (void __user 
**)bufs, frames);
-   }
+   ret = __snd_pcm_lib_xfer(substream, bufs, false, frames,
+in_kernel);
if (ret != -EPIPE && ret != -ESTRPIPE)
break;
}
@@ -1650,27 +1614,10 @@ static int snd_pcm_oss_sync(struct snd_pcm_oss_file 
*pcm_oss_file)
size = runtime->control->appl_ptr % runtime->period_size;
if (size > 0) {
size = runtime->period_size - size;
-  

[PATCH v2 26/27] ALSA: pcm: Build OSS writev/readv helpers conditionally

2017-06-01 Thread Takashi Iwai
The snd_pcm_oss_writev3() and snd_pcm_oss_readv3() are used only in
io.c with CONFIG_SND_PCM_OSS_PLUGINS=y.  Add an ifdef to reduce the
build of these functions.

Along with it, since they are called always for in-kernel copy, reduce
the argument and call snd_pcm_kernel_writev() and *_readv() directly
instead.

Signed-off-by: Takashi Iwai <ti...@suse.de>
---
 sound/core/oss/io.c |  4 ++--
 sound/core/oss/pcm_oss.c| 12 ++--
 sound/core/oss/pcm_plugin.h |  6 ++
 3 files changed, 10 insertions(+), 12 deletions(-)

diff --git a/sound/core/oss/io.c b/sound/core/oss/io.c
index 6faa1d719206..d870b2d93135 100644
--- a/sound/core/oss/io.c
+++ b/sound/core/oss/io.c
@@ -26,9 +26,9 @@
 #include "pcm_plugin.h"
 
 #define pcm_write(plug,buf,count) snd_pcm_oss_write3(plug,buf,count,1)
-#define pcm_writev(plug,vec,count) snd_pcm_oss_writev3(plug,vec,count,1)
+#define pcm_writev(plug,vec,count) snd_pcm_oss_writev3(plug,vec,count)
 #define pcm_read(plug,buf,count) snd_pcm_oss_read3(plug,buf,count,1)
-#define pcm_readv(plug,vec,count) snd_pcm_oss_readv3(plug,vec,count,1)
+#define pcm_readv(plug,vec,count) snd_pcm_oss_readv3(plug,vec,count)
 
 /*
  *  Basic io plugin
diff --git a/sound/core/oss/pcm_oss.c b/sound/core/oss/pcm_oss.c
index 2d6a825cfe88..5e1009d959a8 100644
--- a/sound/core/oss/pcm_oss.c
+++ b/sound/core/oss/pcm_oss.c
@@ -1232,7 +1232,8 @@ snd_pcm_sframes_t snd_pcm_oss_read3(struct 
snd_pcm_substream *substream, char *p
return ret;
 }
 
-snd_pcm_sframes_t snd_pcm_oss_writev3(struct snd_pcm_substream *substream, 
void **bufs, snd_pcm_uframes_t frames, int in_kernel)
+#ifdef CONFIG_SND_PCM_OSS_PLUGINS
+snd_pcm_sframes_t snd_pcm_oss_writev3(struct snd_pcm_substream *substream, 
void **bufs, snd_pcm_uframes_t frames)
 {
struct snd_pcm_runtime *runtime = substream->runtime;
int ret;
@@ -1249,8 +1250,7 @@ snd_pcm_sframes_t snd_pcm_oss_writev3(struct 
snd_pcm_substream *substream, void
if (ret < 0)
break;
}
-   ret = __snd_pcm_lib_xfer(substream, bufs, false, frames,
-in_kernel);
+   ret = snd_pcm_kernel_writev(substream, bufs, frames);
if (ret != -EPIPE && ret != -ESTRPIPE)
break;
 
@@ -1262,7 +1262,7 @@ snd_pcm_sframes_t snd_pcm_oss_writev3(struct 
snd_pcm_substream *substream, void
return ret;
 }

-snd_pcm_sframes_t snd_pcm_oss_readv3(struct snd_pcm_substream *substream, void 
**bufs, snd_pcm_uframes_t frames, int in_kernel)
+snd_pcm_sframes_t snd_pcm_oss_readv3(struct snd_pcm_substream *substream, void 
**bufs, snd_pcm_uframes_t frames)
 {
struct snd_pcm_runtime *runtime = substream->runtime;
int ret;
@@ -1283,13 +1283,13 @@ snd_pcm_sframes_t snd_pcm_oss_readv3(struct 
snd_pcm_substream *substream, void *
if (ret < 0)
break;
}
-   ret = __snd_pcm_lib_xfer(substream, bufs, false, frames,
-in_kernel);
+   ret = snd_pcm_kernel_readv(substream, bufs, frames);
if (ret != -EPIPE && ret != -ESTRPIPE)
break;
}
return ret;
 }
+#endif /* CONFIG_SND_PCM_OSS_PLUGINS */
 
 static ssize_t snd_pcm_oss_write2(struct snd_pcm_substream *substream, const 
char *buf, size_t bytes, int in_kernel)
 {
diff --git a/sound/core/oss/pcm_plugin.h b/sound/core/oss/pcm_plugin.h
index 73c068abaca5..c9cd29d86efd 100644
--- a/sound/core/oss/pcm_plugin.h
+++ b/sound/core/oss/pcm_plugin.h
@@ -162,11 +162,9 @@ snd_pcm_sframes_t snd_pcm_oss_write3(struct 
snd_pcm_substream *substream,
 snd_pcm_sframes_t snd_pcm_oss_read3(struct snd_pcm_substream *substream,
char *ptr, snd_pcm_uframes_t size, int 
in_kernel);
 snd_pcm_sframes_t snd_pcm_oss_writev3(struct snd_pcm_substream *substream,
- void **bufs, snd_pcm_uframes_t frames,
- int in_kernel);
+ void **bufs, snd_pcm_uframes_t frames);
 snd_pcm_sframes_t snd_pcm_oss_readv3(struct snd_pcm_substream *substream,
-void **bufs, snd_pcm_uframes_t frames,
-int in_kernel);
+void **bufs, snd_pcm_uframes_t frames);
 
 #else
 
-- 
2.13.0



[PATCH v2 16/27] ALSA: pcm: Drop the old copy and silence ops

2017-06-01 Thread Takashi Iwai
Now that all users of old copy and silence ops have been converted to
the new PCM ops, the old stuff can be retired and go away.

Signed-off-by: Takashi Iwai <ti...@suse.de>
---
 include/sound/pcm.h  |  5 -
 sound/core/pcm_lib.c | 38 +-
 sound/soc/soc-pcm.c  |  2 --
 3 files changed, 1 insertion(+), 44 deletions(-)

diff --git a/include/sound/pcm.h b/include/sound/pcm.h
index a065415191d8..953ebfc83184 100644
--- a/include/sound/pcm.h
+++ b/include/sound/pcm.h
@@ -78,11 +78,6 @@ struct snd_pcm_ops {
struct timespec *system_ts, struct timespec *audio_ts,
struct snd_pcm_audio_tstamp_config *audio_tstamp_config,
struct snd_pcm_audio_tstamp_report 
*audio_tstamp_report);
-   int (*copy)(struct snd_pcm_substream *substream, int channel,
-   snd_pcm_uframes_t pos,
-   void __user *buf, snd_pcm_uframes_t count);
-   int (*silence)(struct snd_pcm_substream *substream, int channel, 
-  snd_pcm_uframes_t pos, snd_pcm_uframes_t count);
int (*fill_silence)(struct snd_pcm_substream *substream, int channel,
unsigned long pos, unsigned long bytes);
int (*copy_user)(struct snd_pcm_substream *substream, int channel,
diff --git a/sound/core/pcm_lib.c b/sound/core/pcm_lib.c
index 9334fc2c20c8..0db8d4e0fca2 100644
--- a/sound/core/pcm_lib.c
+++ b/sound/core/pcm_lib.c
@@ -116,9 +116,6 @@ void snd_pcm_playback_silence(struct snd_pcm_substream 
*substream, snd_pcm_ufram
   
frames_to_bytes(runtime, ofs),
   
frames_to_bytes(runtime, transfer));
snd_BUG_ON(err < 0);
-   } else if (substream->ops->silence) {
-   err = substream->ops->silence(substream, -1, 
ofs, transfer);
-   snd_BUG_ON(err < 0);
} else {
hwbuf = runtime->dma_area + 
frames_to_bytes(runtime, ofs);
snd_pcm_format_set_silence(runtime->format, 
hwbuf, transfer * runtime->channels);
@@ -133,11 +130,6 @@ void snd_pcm_playback_silence(struct snd_pcm_substream 
*substream, snd_pcm_ufram
   
samples_to_bytes(runtime, transfer));
snd_BUG_ON(err < 0);
}
-   } else if (substream->ops->silence) {
-   for (c = 0; c < channels; ++c) {
-   err = 
substream->ops->silence(substream, c, ofs, transfer);
-   snd_BUG_ON(err < 0);
-   }
} else {
size_t dma_csize = runtime->dma_bytes / 
channels;
for (c = 0; c < channels; ++c) {
@@ -2013,9 +2005,6 @@ static int snd_pcm_lib_write_transfer(struct 
snd_pcm_substream *substream,
err = substream->ops->copy_user(substream, 0, hwoff, buf, 
frames);
if (err < 0)
return err;
-   } else if (substream->ops->copy) {
-   if ((err = substream->ops->copy(substream, -1, hwoff, buf, 
frames)) < 0)
-   return err;
} else {
char *hwbuf = runtime->dma_area + frames_to_bytes(runtime, 
hwoff);
if (copy_from_user(hwbuf, buf, frames_to_bytes(runtime, 
frames)))
@@ -2137,8 +2126,7 @@ static int pcm_sanity_check(struct snd_pcm_substream 
*substream)
if (PCM_RUNTIME_CHECK(substream))
return -ENXIO;
runtime = substream->runtime;
-   if (snd_BUG_ON(!substream->ops->copy_user && !substream->ops->copy
-  && !runtime->dma_area))
+   if (snd_BUG_ON(!substream->ops->copy_user && !runtime->dma_area))
return -EINVAL;
if (runtime->status->state == SNDRV_PCM_STATE_OPEN)
return -EBADFD;
@@ -2198,19 +2186,6 @@ static int snd_pcm_lib_writev_transfer(struct 
snd_pcm_substream *substream,
if (err < 0)
return err;
}
-   } else if (substream->ops->copy) {
-   if (snd_BUG_ON(!substream->ops->silence))
-   return -EINVAL;
-   for (c = 0; c < channels; ++c, ++bufs) {
-   if (*bufs == NULL) {
-   if ((err = substream->ops->silence(substream, 
c, hwoff, frames)) < 0)
-   return err;
-  

[PATCH v2 07/27] ALSA: rme32: Convert to the new PCM copy ops

2017-06-01 Thread Takashi Iwai
Replace the copy and the silence ops with the new ops.
The conversion is straightforward with standard helper functions, and
now we can drop the bytes <-> frames conversions in callbacks.

Signed-off-by: Takashi Iwai <ti...@suse.de>
---
 sound/pci/rme32.c | 65 ---
 1 file changed, 43 insertions(+), 22 deletions(-)

diff --git a/sound/pci/rme32.c b/sound/pci/rme32.c
index 96d15db65dfd..ce438c62b0b3 100644
--- a/sound/pci/rme32.c
+++ b/sound/pci/rme32.c
@@ -254,39 +254,46 @@ static inline unsigned int snd_rme32_pcm_byteptr(struct 
rme32 * rme32)
 }
 
 /* silence callback for halfduplex mode */
-static int snd_rme32_playback_silence(struct snd_pcm_substream *substream, int 
channel,/* not used (interleaved data) */
- snd_pcm_uframes_t pos,
- snd_pcm_uframes_t count)
+static int snd_rme32_playback_silence(struct snd_pcm_substream *substream,
+ int channel, unsigned long pos,
+ unsigned long count)
 {
struct rme32 *rme32 = snd_pcm_substream_chip(substream);
-   count <<= rme32->playback_frlog;
-   pos <<= rme32->playback_frlog;
+
memset_io(rme32->iobase + RME32_IO_DATA_BUFFER + pos, 0, count);
return 0;
 }
 
 /* copy callback for halfduplex mode */
-static int snd_rme32_playback_copy(struct snd_pcm_substream *substream, int 
channel,   /* not used (interleaved data) */
-  snd_pcm_uframes_t pos,
-  void __user *src, snd_pcm_uframes_t count)
+static int snd_rme32_playback_copy(struct snd_pcm_substream *substream,
+  int channel, unsigned long pos,
+  void __user *src, unsigned long count)
 {
struct rme32 *rme32 = snd_pcm_substream_chip(substream);
-   count <<= rme32->playback_frlog;
-   pos <<= rme32->playback_frlog;
+
if (copy_from_user_toio(rme32->iobase + RME32_IO_DATA_BUFFER + pos,
-   src, count))
+   src, count))
return -EFAULT;
return 0;
 }
 
+static int snd_rme32_playback_copy_kernel(struct snd_pcm_substream *substream,
+ int channel, unsigned long pos,
+ void *src, unsigned long count)
+{
+   struct rme32 *rme32 = snd_pcm_substream_chip(substream);
+
+   memcpy_toio(rme32->iobase + RME32_IO_DATA_BUFFER + pos, src, count);
+   return 0;
+}
+
 /* copy callback for halfduplex mode */
-static int snd_rme32_capture_copy(struct snd_pcm_substream *substream, int 
channel,/* not used (interleaved data) */
- snd_pcm_uframes_t pos,
- void __user *dst, snd_pcm_uframes_t count)
+static int snd_rme32_capture_copy(struct snd_pcm_substream *substream,
+ int channel, unsigned long pos,
+ void __user *dst, unsigned long count)
 {
struct rme32 *rme32 = snd_pcm_substream_chip(substream);
-   count <<= rme32->capture_frlog;
-   pos <<= rme32->capture_frlog;
+
if (copy_to_user_fromio(dst,
rme32->iobase + RME32_IO_DATA_BUFFER + pos,
count))
@@ -294,6 +301,16 @@ static int snd_rme32_capture_copy(struct snd_pcm_substream 
*substream, int chann
return 0;
 }
 
+static int snd_rme32_capture_copy_kernel(struct snd_pcm_substream *substream,
+int channel, unsigned long pos,
+void *dst, unsigned long count)
+{
+   struct rme32 *rme32 = snd_pcm_substream_chip(substream);
+
+   memcpy_fromio(dst, rme32->iobase + RME32_IO_DATA_BUFFER + pos, count);
+   return 0;
+}
+
 /*
  * SPDIF I/O capabilities (half-duplex mode)
  */
@@ -1205,8 +1222,9 @@ static const struct snd_pcm_ops 
snd_rme32_playback_spdif_ops = {
.prepare =  snd_rme32_playback_prepare,
.trigger =  snd_rme32_pcm_trigger,
.pointer =  snd_rme32_playback_pointer,
-   .copy = snd_rme32_playback_copy,
-   .silence =  snd_rme32_playback_silence,
+   .copy_user =snd_rme32_playback_copy,
+   .copy_kernel =  snd_rme32_playback_copy_kernel,
+   .fill_silence = snd_rme32_playback_silence,
.mmap = snd_pcm_lib_mmap_iomem,
 };
 
@@ -1219,7 +1237,8 @@ static const struct snd_pcm_ops 
snd_rme32_capture_spdif_ops = {
.prepare =  snd_rme32_capture_prepare,
.trigger =  snd_rme32_pcm_trigger,
.pointer =  snd_rme32_capture_pointer,
-   .copy = snd_rme32_capture_copy,
+   .copy_user =snd_rme32_c

[PATCH v2 06/27] ALSA: korg1212: Convert to the new PCM ops

2017-06-01 Thread Takashi Iwai
Replace the copy and the silence ops with the new PCM ops.
Although we can refactor this messy code, at this time, the changes
are kept as small as possible.  Let's clean up later.

Signed-off-by: Takashi Iwai <ti...@suse.de>
---
 sound/pci/korg1212/korg1212.c | 112 --
 1 file changed, 65 insertions(+), 47 deletions(-)

diff --git a/sound/pci/korg1212/korg1212.c b/sound/pci/korg1212/korg1212.c
index 1e25095fd144..b28fe4914d6b 100644
--- a/sound/pci/korg1212/korg1212.c
+++ b/sound/pci/korg1212/korg1212.c
@@ -1299,13 +1299,21 @@ static int snd_korg1212_silence(struct snd_korg1212 
*korg1212, int pos, int coun
return 0;
 }
 
-static int snd_korg1212_copy_to(struct snd_korg1212 *korg1212, void __user 
*dst, int pos, int count, int offset, int size)
+static int snd_korg1212_copy_to(struct snd_pcm_substream *substream,
+   void __user *dst, int pos, int count,
+   bool in_kernel)
 {
-   struct KorgAudioFrame * src =  
korg1212->recordDataBufsPtr[0].bufferData + pos;
-   int i, rc;
-
-   K1212_DEBUG_PRINTK_VERBOSE("K1212_DEBUG: snd_korg1212_copy_to pos=%d 
offset=%d size=%d\n",
-  pos, offset, size);
+   struct snd_pcm_runtime *runtime = substream->runtime;
+struct snd_korg1212 *korg1212 = snd_pcm_substream_chip(substream);
+   struct KorgAudioFrame *src;
+   int i, size;
+
+   pos = bytes_to_frames(runtime, pos);
+   count = bytes_to_frames(runtime, count);
+   size = korg1212->channels * 2;
+   src = korg1212->recordDataBufsPtr[0].bufferData + pos;
+   K1212_DEBUG_PRINTK_VERBOSE("K1212_DEBUG: snd_korg1212_copy_to pos=%d 
size=%d count=%d\n",
+  pos, size, count);
if (snd_BUG_ON(pos + count > K1212_MAX_SAMPLES))
return -EINVAL;
 
@@ -1317,11 +1325,10 @@ static int snd_korg1212_copy_to(struct snd_korg1212 
*korg1212, void __user *dst,
return -EFAULT;
}
 #endif
-   rc = copy_to_user(dst + offset, src, size);
-   if (rc) {
-   K1212_DEBUG_PRINTK("K1212_DEBUG: snd_korg1212_copy_to 
USER EFAULT src=%p dst=%p iter=%d\n", src, dst, i);
+   if (in_kernel)
+   memcpy((void *)dst, src, size);
+   else if (copy_to_user(dst, src, size))
return -EFAULT;
-   }
src++;
dst += size;
}
@@ -1329,13 +1336,22 @@ static int snd_korg1212_copy_to(struct snd_korg1212 
*korg1212, void __user *dst,
return 0;
 }
 
-static int snd_korg1212_copy_from(struct snd_korg1212 *korg1212, void __user 
*src, int pos, int count, int offset, int size)
+static int snd_korg1212_copy_from(struct snd_pcm_substream *substream,
+ void __user *src, int pos, int count,
+ bool in_kernel)
 {
-   struct KorgAudioFrame * dst =  korg1212->playDataBufsPtr[0].bufferData 
+ pos;
-   int i, rc;
+struct snd_pcm_runtime *runtime = substream->runtime;
+   struct snd_korg1212 *korg1212 = snd_pcm_substream_chip(substream);
+   struct KorgAudioFrame *dst;
+   int i, size;
 
-   K1212_DEBUG_PRINTK_VERBOSE("K1212_DEBUG: snd_korg1212_copy_from pos=%d 
offset=%d size=%d count=%d\n",
-  pos, offset, size, count);
+   pos = bytes_to_frames(runtime, pos);
+   count = bytes_to_frames(runtime, count);
+   size = korg1212->channels * 2;
+   dst = korg1212->playDataBufsPtr[0].bufferData + pos;
+
+   K1212_DEBUG_PRINTK_VERBOSE("K1212_DEBUG: snd_korg1212_copy_from pos=%d 
size=%d count=%d\n",
+  pos, size, count);
 
if (snd_BUG_ON(pos + count > K1212_MAX_SAMPLES))
return -EINVAL;
@@ -1348,11 +1364,10 @@ static int snd_korg1212_copy_from(struct snd_korg1212 
*korg1212, void __user *sr
return -EFAULT;
}
 #endif
-   rc = copy_from_user((void*) dst + offset, src, size);
-   if (rc) {
-   K1212_DEBUG_PRINTK("K1212_DEBUG: snd_korg1212_copy_from 
USER EFAULT src=%p dst=%p iter=%d\n", src, dst, i);
+   if (in_kernel)
+   memcpy((void *)dst, src, size);
+   else if (copy_from_user(dst, src, size))
return -EFAULT;
-   }
dst++;
src += size;
}
@@ -1640,45 +1655,46 @@ static snd_pcm_uframes_t 
snd_korg1212_capture_pointer(struct snd_pcm_substream *
 }
 
 static int snd_korg1212_playback_copy(struct snd_pcm_substream *substream,
-int channel, /* not used (interleaved data) */
-snd_pcm_uframes_t 

[PATCH v2 09/27] ALSA: rme9652: Convert to the new PCM ops

2017-06-01 Thread Takashi Iwai
Replace the copy and the silence ops with the new PCM ops.
The conversion is straightforward with standard helper functions.

Signed-off-by: Takashi Iwai <ti...@suse.de>
---
 sound/pci/rme9652/rme9652.c | 71 ++---
 1 file changed, 54 insertions(+), 17 deletions(-)

diff --git a/sound/pci/rme9652/rme9652.c b/sound/pci/rme9652/rme9652.c
index 55172c689991..59684bf5cac0 100644
--- a/sound/pci/rme9652/rme9652.c
+++ b/sound/pci/rme9652/rme9652.c
@@ -1883,13 +1883,14 @@ static char *rme9652_channel_buffer_location(struct 
snd_rme9652 *rme9652,
}
 }
 
-static int snd_rme9652_playback_copy(struct snd_pcm_substream *substream, int 
channel,
-snd_pcm_uframes_t pos, void __user *src, 
snd_pcm_uframes_t count)
+static int snd_rme9652_playback_copy(struct snd_pcm_substream *substream,
+int channel, unsigned long pos,
+void __user *src, unsigned long count)
 {
struct snd_rme9652 *rme9652 = snd_pcm_substream_chip(substream);
char *channel_buf;
 
-   if (snd_BUG_ON(pos + count > RME9652_CHANNEL_BUFFER_BYTES / 4))
+   if (snd_BUG_ON(pos + count > RME9652_CHANNEL_BUFFER_BYTES))
return -EINVAL;
 
channel_buf = rme9652_channel_buffer_location (rme9652,
@@ -1897,18 +1898,35 @@ static int snd_rme9652_playback_copy(struct 
snd_pcm_substream *substream, int ch
   channel);
if (snd_BUG_ON(!channel_buf))
return -EIO;
-   if (copy_from_user(channel_buf + pos * 4, src, count * 4))
+   if (copy_from_user(channel_buf + pos, src, count))
return -EFAULT;
-   return count;
+   return 0;
 }
 
-static int snd_rme9652_capture_copy(struct snd_pcm_substream *substream, int 
channel,
-   snd_pcm_uframes_t pos, void __user *dst, 
snd_pcm_uframes_t count)
+static int snd_rme9652_playback_copy_kernel(struct snd_pcm_substream 
*substream,
+   int channel, unsigned long pos,
+   void *src, unsigned long count)
 {
struct snd_rme9652 *rme9652 = snd_pcm_substream_chip(substream);
char *channel_buf;
 
-   if (snd_BUG_ON(pos + count > RME9652_CHANNEL_BUFFER_BYTES / 4))
+   channel_buf = rme9652_channel_buffer_location(rme9652,
+ substream->pstr->stream,
+ channel);
+   if (snd_BUG_ON(!channel_buf))
+   return -EIO;
+   memcpy(channel_buf + pos, src, count);
+   return 0;
+}
+
+static int snd_rme9652_capture_copy(struct snd_pcm_substream *substream,
+   int channel, unsigned long pos,
+   void __user *dst, unsigned long count)
+{
+   struct snd_rme9652 *rme9652 = snd_pcm_substream_chip(substream);
+   char *channel_buf;
+
+   if (snd_BUG_ON(pos + count > RME9652_CHANNEL_BUFFER_BYTES))
return -EINVAL;
 
channel_buf = rme9652_channel_buffer_location (rme9652,
@@ -1916,13 +1934,30 @@ static int snd_rme9652_capture_copy(struct 
snd_pcm_substream *substream, int cha
   channel);
if (snd_BUG_ON(!channel_buf))
return -EIO;
-   if (copy_to_user(dst, channel_buf + pos * 4, count * 4))
+   if (copy_to_user(dst, channel_buf + pos, count))
return -EFAULT;
-   return count;
+   return 0;
 }
 
-static int snd_rme9652_hw_silence(struct snd_pcm_substream *substream, int 
channel,
- snd_pcm_uframes_t pos, snd_pcm_uframes_t 
count)
+static int snd_rme9652_capture_copy_kernel(struct snd_pcm_substream *substream,
+  int channel, unsigned long pos,
+  void *dst, unsigned long count)
+{
+   struct snd_rme9652 *rme9652 = snd_pcm_substream_chip(substream);
+   char *channel_buf;
+
+   channel_buf = rme9652_channel_buffer_location(rme9652,
+ substream->pstr->stream,
+ channel);
+   if (snd_BUG_ON(!channel_buf))
+   return -EIO;
+   memcpy(dst, channel_buf + pos, count);
+   return 0;
+}
+
+static int snd_rme9652_hw_silence(struct snd_pcm_substream *substream,
+ int channel, unsigned long pos,
+ unsigned long count)
 {
struct snd_rme9652 *rme9652 = snd_pcm_substream_chip(substream);
char *channel_buf;
@@ -1932,8 +1967,8 @@ static int snd_rme9652_hw_silence(struct 
snd_pcm_substream *substream, int chann

[PATCH v2 21/27] ALSA: pcm: Unify read/write loop

2017-06-01 Thread Takashi Iwai
Both __snd_pcm_lib_read() and __snd_pcm_write() functions have almost
the same code to loop over samples.  For simplification, this patch
unifies both as the single helper, __snd_pcm_lib_xfer().

Other than that, there should be no functional change by this patch.

Signed-off-by: Takashi Iwai <ti...@suse.de>
---
 include/sound/pcm.h  |  13 ++--
 sound/core/pcm_lib.c | 184 +--
 2 files changed, 51 insertions(+), 146 deletions(-)

diff --git a/include/sound/pcm.h b/include/sound/pcm.h
index cb4eff8ffd2e..173c6a6ebf35 100644
--- a/include/sound/pcm.h
+++ b/include/sound/pcm.h
@@ -1088,10 +1088,7 @@ int snd_pcm_update_state(struct snd_pcm_substream 
*substream,
 int snd_pcm_update_hw_ptr(struct snd_pcm_substream *substream);
 void snd_pcm_playback_silence(struct snd_pcm_substream *substream, 
snd_pcm_uframes_t new_hw_ptr);
 void snd_pcm_period_elapsed(struct snd_pcm_substream *substream);
-snd_pcm_sframes_t __snd_pcm_lib_write(struct snd_pcm_substream *substream,
- void *buf, bool interleaved,
- snd_pcm_uframes_t frames);
-snd_pcm_sframes_t __snd_pcm_lib_read(struct snd_pcm_substream *substream,
+snd_pcm_sframes_t __snd_pcm_lib_xfer(struct snd_pcm_substream *substream,
 void *buf, bool interleaved,
 snd_pcm_uframes_t frames);
 
@@ -1099,28 +1096,28 @@ static inline snd_pcm_sframes_t
 snd_pcm_lib_write(struct snd_pcm_substream *substream,
  const void __user *buf, snd_pcm_uframes_t frames)
 {
-   return __snd_pcm_lib_write(substream, (void *)buf, true, frames);
+   return __snd_pcm_lib_xfer(substream, (void *)buf, true, frames);
 }
 
 static inline snd_pcm_sframes_t
 snd_pcm_lib_read(struct snd_pcm_substream *substream,
 void __user *buf, snd_pcm_uframes_t frames)
 {
-   return __snd_pcm_lib_read(substream, (void *)buf, true, frames);
+   return __snd_pcm_lib_xfer(substream, (void *)buf, true, frames);
 }
 
 static inline snd_pcm_sframes_t
 snd_pcm_lib_writev(struct snd_pcm_substream *substream,
   void __user **bufs, snd_pcm_uframes_t frames)
 {
-   return __snd_pcm_lib_write(substream, (void *)bufs, false, frames);
+   return __snd_pcm_lib_xfer(substream, (void *)bufs, false, frames);
 }
 
 static inline snd_pcm_sframes_t
 snd_pcm_lib_readv(struct snd_pcm_substream *substream,
  void __user **bufs, snd_pcm_uframes_t frames)
 {
-   return __snd_pcm_lib_read(substream, (void *)bufs, false, frames);
+   return __snd_pcm_lib_xfer(substream, (void *)bufs, false, frames);
 }
 
 extern const struct snd_pcm_hw_constraint_list snd_pcm_known_rates;
diff --git a/sound/core/pcm_lib.c b/sound/core/pcm_lib.c
index eb9cbc2d9d7b..f15460eaf8b5 100644
--- a/sound/core/pcm_lib.c
+++ b/sound/core/pcm_lib.c
@@ -2006,13 +2006,13 @@ static void *get_dma_ptr(struct snd_pcm_runtime 
*runtime,
channel * (runtime->dma_bytes / runtime->channels);
 }
 
-/* default copy_user ops for write */
-static int default_write_copy_user(struct snd_pcm_substream *substream,
-  int channel, unsigned long hwoff,
-  void __user *buf, unsigned long bytes)
+/* default copy_user ops for write; used for both interleaved and non- modes */
+static int default_write_copy(struct snd_pcm_substream *substream,
+ int channel, unsigned long hwoff,
+ void *buf, unsigned long bytes)
 {
if (copy_from_user(get_dma_ptr(substream->runtime, channel, hwoff),
-  buf, bytes))
+  (void __user *)buf, bytes))
return -EFAULT;
return 0;
 }
@@ -2038,6 +2038,18 @@ static int fill_silence(struct snd_pcm_substream 
*substream, int channel,
return 0;
 }
 
+/* default copy_user ops for read; used for both interleaved and non- modes */
+static int default_read_copy(struct snd_pcm_substream *substream,
+int channel, unsigned long hwoff,
+void *buf, unsigned long bytes)
+{
+   if (copy_to_user((void __user *)buf,
+get_dma_ptr(substream->runtime, channel, hwoff),
+bytes))
+   return -EFAULT;
+   return 0;
+}
+
 /* call transfer function with the converted pointers and sizes;
  * for interleaved mode, it's one shot for all samples
  */
@@ -2119,9 +2131,10 @@ static int pcm_accessible_state(struct snd_pcm_runtime 
*runtime)
}
 }
 
-snd_pcm_sframes_t __snd_pcm_lib_write(struct snd_pcm_substream *substream,
- void *data, bool interleaved,
- snd_pcm_uframes_t size)
+/* the common loop for read/write data */
+snd_pcm_sframes_t __snd_pcm_lib_xfer(struct snd_pcm_su

[PATCH 14/16] ASoC: blackfin: Convert to copy_silence ops

2017-05-21 Thread Takashi Iwai
Replace the copy and the silence ops with the new merged ops.
The silence is performed only when CONFIG_SND_BF5XX_MMAP_SUPPORT is
set (since copy_silence ops is set only with this config), so in
bf5xx-ac97.c we have a bit tricky macro for a slight optimization.

Note that we don't need to take in_kernel into account on this
architecture, so the conversion is easy otherwise.

Signed-off-by: Takashi Iwai <ti...@suse.de>
---
 sound/soc/blackfin/bf5xx-ac97-pcm.c |  6 ++---
 sound/soc/blackfin/bf5xx-ac97.c | 18 ++-
 sound/soc/blackfin/bf5xx-i2s-pcm.c  | 46 -
 3 files changed, 30 insertions(+), 40 deletions(-)

diff --git a/sound/soc/blackfin/bf5xx-ac97-pcm.c 
b/sound/soc/blackfin/bf5xx-ac97-pcm.c
index 02ad2606fa19..2fdffa7d376c 100644
--- a/sound/soc/blackfin/bf5xx-ac97-pcm.c
+++ b/sound/soc/blackfin/bf5xx-ac97-pcm.c
@@ -280,8 +280,8 @@ static int bf5xx_pcm_mmap(struct snd_pcm_substream 
*substream,
 }
 #else
 static int bf5xx_pcm_copy(struct snd_pcm_substream *substream, int channel,
-   snd_pcm_uframes_t pos,
-   void __user *buf, snd_pcm_uframes_t count)
+  snd_pcm_uframes_t pos, void __user *buf,
+  snd_pcm_uframes_t count, bool in_kernel)
 {
struct snd_pcm_runtime *runtime = substream->runtime;
unsigned int chan_mask = ac97_chan_mask[runtime->channels - 1];
@@ -309,7 +309,7 @@ static struct snd_pcm_ops bf5xx_pcm_ac97_ops = {
 #if defined(CONFIG_SND_BF5XX_MMAP_SUPPORT)
.mmap   = bf5xx_pcm_mmap,
 #else
-   .copy   = bf5xx_pcm_copy,
+   .copy_silence   = bf5xx_pcm_copy,
 #endif
 };
 
diff --git a/sound/soc/blackfin/bf5xx-ac97.c b/sound/soc/blackfin/bf5xx-ac97.c
index a040cfe29fc0..d1f11d9ecb07 100644
--- a/sound/soc/blackfin/bf5xx-ac97.c
+++ b/sound/soc/blackfin/bf5xx-ac97.c
@@ -43,35 +43,41 @@
 
 static struct sport_device *ac97_sport_handle;
 
+#ifdef CONFIG_SND_BF5XX_MMAP_SUPPORT
+#define GET_VAL(src)   (*src++)/* copy only */
+#else
+#define GET_VAL(src)   (src ? *src++ : 0)  /* copy/silence */
+#endif
+
 void bf5xx_pcm_to_ac97(struct ac97_frame *dst, const __u16 *src,
size_t count, unsigned int chan_mask)
 {
while (count--) {
dst->ac97_tag = TAG_VALID;
if (chan_mask & SP_FL) {
-   dst->ac97_pcm_r = *src++;
+   dst->ac97_pcm_r = GET_VAL(src);
dst->ac97_tag |= TAG_PCM_RIGHT;
}
if (chan_mask & SP_FR) {
-   dst->ac97_pcm_l = *src++;
+   dst->ac97_pcm_l = GET_VAL(src);
dst->ac97_tag |= TAG_PCM_LEFT;
 
}
 #if defined(CONFIG_SND_BF5XX_MULTICHAN_SUPPORT)
if (chan_mask & SP_SR) {
-   dst->ac97_sl = *src++;
+   dst->ac97_sl = GET_VAL(src);
dst->ac97_tag |= TAG_PCM_SL;
}
if (chan_mask & SP_SL) {
-   dst->ac97_sr = *src++;
+   dst->ac97_sr = GET_VAL(src);
dst->ac97_tag |= TAG_PCM_SR;
}
if (chan_mask & SP_LFE) {
-   dst->ac97_lfe = *src++;
+   dst->ac97_lfe = GET_VAL(src);
dst->ac97_tag |= TAG_PCM_LFE;
}
if (chan_mask & SP_FC) {
-   dst->ac97_center = *src++;
+   dst->ac97_center = GET_VAL(src);
dst->ac97_tag |= TAG_PCM_CENTER;
}
 #endif
diff --git a/sound/soc/blackfin/bf5xx-i2s-pcm.c 
b/sound/soc/blackfin/bf5xx-i2s-pcm.c
index 6cba211da32e..5686c29fb058 100644
--- a/sound/soc/blackfin/bf5xx-i2s-pcm.c
+++ b/sound/soc/blackfin/bf5xx-i2s-pcm.c
@@ -226,7 +226,8 @@ static int bf5xx_pcm_mmap(struct snd_pcm_substream 
*substream,
 }
 
 static int bf5xx_pcm_copy(struct snd_pcm_substream *substream, int channel,
-   snd_pcm_uframes_t pos, void *buf, snd_pcm_uframes_t count)
+ snd_pcm_uframes_t pos, void *buf,
+ snd_pcm_uframes_t count, bool in_kernel)
 {
struct snd_soc_pcm_runtime *rtd = substream->private_data;
struct snd_pcm_runtime *runtime = substream->runtime;
@@ -245,8 +246,14 @@ static int bf5xx_pcm_copy(struct snd_pcm_substream 
*substream, int channel,
 
while (count--) {
for (i = 0; i < runtime->channels; i++) {
-   memcpy(dst + dma_data->map[i] *
-   sample_size, src, sample_size);
+   if (!buf)
+

[PATCH 16/16] ALSA: pcm: Drop the old copy and silence ops

2017-05-21 Thread Takashi Iwai
Now that all users of old copy and silence ops have been converted to
the new copy_silence ops, the old stuff can be retired and go away.

Signed-off-by: Takashi Iwai <ti...@suse.de>
---
 include/sound/pcm.h  |  5 -
 sound/core/pcm_lib.c | 38 +-
 sound/soc/soc-pcm.c  |  2 --
 3 files changed, 1 insertion(+), 44 deletions(-)

diff --git a/include/sound/pcm.h b/include/sound/pcm.h
index b9dd813dd885..4243c02c3f11 100644
--- a/include/sound/pcm.h
+++ b/include/sound/pcm.h
@@ -78,11 +78,6 @@ struct snd_pcm_ops {
struct timespec *system_ts, struct timespec *audio_ts,
struct snd_pcm_audio_tstamp_config *audio_tstamp_config,
struct snd_pcm_audio_tstamp_report 
*audio_tstamp_report);
-   int (*copy)(struct snd_pcm_substream *substream, int channel,
-   snd_pcm_uframes_t pos,
-   void __user *buf, snd_pcm_uframes_t count);
-   int (*silence)(struct snd_pcm_substream *substream, int channel, 
-  snd_pcm_uframes_t pos, snd_pcm_uframes_t count);
int (*copy_silence)(struct snd_pcm_substream *substream, int channel,
snd_pcm_uframes_t pos, void __user *buf,
snd_pcm_uframes_t count, bool in_kernel);
diff --git a/sound/core/pcm_lib.c b/sound/core/pcm_lib.c
index b720cbda017f..1c9d43fefacc 100644
--- a/sound/core/pcm_lib.c
+++ b/sound/core/pcm_lib.c
@@ -115,9 +115,6 @@ void snd_pcm_playback_silence(struct snd_pcm_substream 
*substream, snd_pcm_ufram
err = substream->ops->copy_silence(substream,
-1, ofs, NULL, transfer, false);
snd_BUG_ON(err < 0);
-   } else if (substream->ops->silence) {
-   err = substream->ops->silence(substream, -1, 
ofs, transfer);
-   snd_BUG_ON(err < 0);
} else {
hwbuf = runtime->dma_area + 
frames_to_bytes(runtime, ofs);
snd_pcm_format_set_silence(runtime->format, 
hwbuf, transfer * runtime->channels);
@@ -131,11 +128,6 @@ void snd_pcm_playback_silence(struct snd_pcm_substream 
*substream, snd_pcm_ufram
c, ofs, NULL, transfer, false);
snd_BUG_ON(err < 0);
}
-   } else if (substream->ops->silence) {
-   for (c = 0; c < channels; ++c) {
-   err = 
substream->ops->silence(substream, c, ofs, transfer);
-   snd_BUG_ON(err < 0);
-   }
} else {
size_t dma_csize = runtime->dma_bytes / 
channels;
for (c = 0; c < channels; ++c) {
@@ -2010,9 +2002,6 @@ static int snd_pcm_lib_write_transfer(struct 
snd_pcm_substream *substream,
   frames, false);
if (err < 0)
return err;
-   } else if (substream->ops->copy) {
-   if ((err = substream->ops->copy(substream, -1, hwoff, buf, 
frames)) < 0)
-   return err;
} else {
char *hwbuf = runtime->dma_area + frames_to_bytes(runtime, 
hwoff);
if (copy_from_user(hwbuf, buf, frames_to_bytes(runtime, 
frames)))
@@ -2134,8 +2123,7 @@ static int pcm_sanity_check(struct snd_pcm_substream 
*substream)
if (PCM_RUNTIME_CHECK(substream))
return -ENXIO;
runtime = substream->runtime;
-   if (snd_BUG_ON(!substream->ops->copy_silence && !substream->ops->copy
-  && !runtime->dma_area))
+   if (snd_BUG_ON(!substream->ops->copy_silence && !runtime->dma_area))
return -EINVAL;
if (runtime->status->state == SNDRV_PCM_STATE_OPEN)
return -EBADFD;
@@ -2186,19 +2174,6 @@ static int snd_pcm_lib_writev_transfer(struct 
snd_pcm_substream *substream,
if (err < 0)
return err;
}
-   } else if (substream->ops->copy) {
-   if (snd_BUG_ON(!substream->ops->silence))
-   return -EINVAL;
-   for (c = 0; c < channels; ++c, ++bufs) {
-   if (*bufs == NULL) {
-   if ((err = substream->ops->silence(substream, 
c, hwoff, frames)) < 0)
-   return err;
-   } else {
-   buf = *bufs + samples_to_bytes

[PATCH 15/16] [media] solo6x10: Convert to copy_silence ops

2017-05-21 Thread Takashi Iwai
Replace the copy and the silence ops with the new merged ops.
It's a capture stream, thus no silence is needed.

Signed-off-by: Takashi Iwai <ti...@suse.de>
---
 drivers/media/pci/solo6x10/solo6x10-g723.c | 13 +++--
 1 file changed, 7 insertions(+), 6 deletions(-)

diff --git a/drivers/media/pci/solo6x10/solo6x10-g723.c 
b/drivers/media/pci/solo6x10/solo6x10-g723.c
index 36e93540bb49..e21db3efb748 100644
--- a/drivers/media/pci/solo6x10/solo6x10-g723.c
+++ b/drivers/media/pci/solo6x10/solo6x10-g723.c
@@ -225,7 +225,7 @@ static snd_pcm_uframes_t snd_solo_pcm_pointer(struct 
snd_pcm_substream *ss)
 
 static int snd_solo_pcm_copy(struct snd_pcm_substream *ss, int channel,
 snd_pcm_uframes_t pos, void __user *dst,
-snd_pcm_uframes_t count)
+snd_pcm_uframes_t count, bool in_kernel)
 {
struct solo_snd_pcm *solo_pcm = snd_pcm_substream_chip(ss);
struct solo_dev *solo_dev = solo_pcm->solo_dev;
@@ -242,10 +242,11 @@ static int snd_solo_pcm_copy(struct snd_pcm_substream 
*ss, int channel,
if (err)
return err;
 
-   err = copy_to_user(dst + (i * G723_PERIOD_BYTES),
-  solo_pcm->g723_buf, G723_PERIOD_BYTES);
-
-   if (err)
+   if (in_kernel)
+   memcpy((void *)dst + (i * G723_PERIOD_BYTES),
+  solo_pcm->g723_buf, G723_PERIOD_BYTES);
+   else if (copy_to_user(dst + (i * G723_PERIOD_BYTES),
+ solo_pcm->g723_buf, G723_PERIOD_BYTES))
return -EFAULT;
}
 
@@ -261,7 +262,7 @@ static const struct snd_pcm_ops snd_solo_pcm_ops = {
.prepare = snd_solo_pcm_prepare,
.trigger = snd_solo_pcm_trigger,
.pointer = snd_solo_pcm_pointer,
-   .copy = snd_solo_pcm_copy,
+   .copy_silence = snd_solo_pcm_copy,
 };
 
 static int snd_solo_capture_volume_info(struct snd_kcontrol *kcontrol,
-- 
2.13.0



[PATCH 01/16] ALSA: pcm: Introduce copy_silence PCM ops

2017-05-21 Thread Takashi Iwai
For supporting the explicit in-kernel copy of PCM buffer data, and
also for reducing the redundant codes for both PCM copy and silence
callbacks, a new ops copy_silence is introduced in this patch.  This
is supposed to serve for both copy and silence operations.  The
silence operation is distinguished by NULL buffer passed (required
only in playback direction).

Also, the callback receives a new boolean flag, in_kernel, which
indicates that the callback gets called for copying the data from/to
the kernel buffer instead of the user-space buffer.  The in_kernel
flag will be used mainly in PCM OSS code for the on-the-fly
conversion.  As this patch stands, only in_kernel=false is passed.
The actual usage of in_kernel=true will be introduced later.

Signed-off-by: Takashi Iwai <ti...@suse.de>
---
 include/sound/pcm.h  |  3 +++
 sound/core/pcm_lib.c | 74 +---
 sound/soc/soc-pcm.c  |  1 +
 3 files changed, 63 insertions(+), 15 deletions(-)

diff --git a/include/sound/pcm.h b/include/sound/pcm.h
index c609b891c4c2..b9dd813dd885 100644
--- a/include/sound/pcm.h
+++ b/include/sound/pcm.h
@@ -83,6 +83,9 @@ struct snd_pcm_ops {
void __user *buf, snd_pcm_uframes_t count);
int (*silence)(struct snd_pcm_substream *substream, int channel, 
   snd_pcm_uframes_t pos, snd_pcm_uframes_t count);
+   int (*copy_silence)(struct snd_pcm_substream *substream, int channel,
+   snd_pcm_uframes_t pos, void __user *buf,
+   snd_pcm_uframes_t count, bool in_kernel);
struct page *(*page)(struct snd_pcm_substream *substream,
 unsigned long offset);
int (*mmap)(struct snd_pcm_substream *substream, struct vm_area_struct 
*vma);
diff --git a/sound/core/pcm_lib.c b/sound/core/pcm_lib.c
index ab4b1d1e44ee..b720cbda017f 100644
--- a/sound/core/pcm_lib.c
+++ b/sound/core/pcm_lib.c
@@ -55,6 +55,8 @@ void snd_pcm_playback_silence(struct snd_pcm_substream 
*substream, snd_pcm_ufram
 {
struct snd_pcm_runtime *runtime = substream->runtime;
snd_pcm_uframes_t frames, ofs, transfer;
+   char *hwbuf;
+   int err;
 
if (runtime->silence_size < runtime->boundary) {
snd_pcm_sframes_t noise_dist, n;
@@ -109,27 +111,35 @@ void snd_pcm_playback_silence(struct snd_pcm_substream 
*substream, snd_pcm_ufram
transfer = ofs + frames > runtime->buffer_size ? 
runtime->buffer_size - ofs : frames;
if (runtime->access == SNDRV_PCM_ACCESS_RW_INTERLEAVED ||
runtime->access == SNDRV_PCM_ACCESS_MMAP_INTERLEAVED) {
-   if (substream->ops->silence) {
-   int err;
+   if (substream->ops->copy_silence) {
+   err = substream->ops->copy_silence(substream,
+   -1, ofs, NULL, transfer, false);
+   snd_BUG_ON(err < 0);
+   } else if (substream->ops->silence) {
err = substream->ops->silence(substream, -1, 
ofs, transfer);
snd_BUG_ON(err < 0);
} else {
-   char *hwbuf = runtime->dma_area + 
frames_to_bytes(runtime, ofs);
+   hwbuf = runtime->dma_area + 
frames_to_bytes(runtime, ofs);
snd_pcm_format_set_silence(runtime->format, 
hwbuf, transfer * runtime->channels);
}
} else {
unsigned int c;
unsigned int channels = runtime->channels;
-   if (substream->ops->silence) {
+   if (substream->ops->copy_silence) {
+   for (c = 0; c < channels; ++c) {
+   err = 
substream->ops->copy_silence(substream,
+   c, ofs, NULL, transfer, false);
+   snd_BUG_ON(err < 0);
+   }
+   } else if (substream->ops->silence) {
for (c = 0; c < channels; ++c) {
-   int err;
err = 
substream->ops->silence(substream, c, ofs, transfer);
snd_BUG_ON(err < 0);
}
} else {
size_t dma_csize = runtime->dma_bytes / 
channels;
for (c = 0; c < channels; ++c) {
-   char *hwbuf = runtime->dma_area + (c * 
dma_csize) + samples_to_by

[PATCH 12/16] ALSA: sb: Convert to copy_silence ops

2017-05-21 Thread Takashi Iwai
Replace the copy and the silence ops with the new merged ops.
We could reduce the redundant silence code by that.

Signed-off-by: Takashi Iwai <ti...@suse.de>
---
 sound/isa/sb/emu8000_pcm.c | 99 ++
 1 file changed, 30 insertions(+), 69 deletions(-)

diff --git a/sound/isa/sb/emu8000_pcm.c b/sound/isa/sb/emu8000_pcm.c
index 32f234f494e5..fd42ae2f73b8 100644
--- a/sound/isa/sb/emu8000_pcm.c
+++ b/sound/isa/sb/emu8000_pcm.c
@@ -422,16 +422,28 @@ do { \
return -EAGAIN;\
 } while (0)
 
+static inline int get_val(unsigned short *sval, unsigned short __user *buf,
+ bool in_kernel)
+{
+   if (!buf)
+   *sval = 0;
+   else if (in_kernel)
+   *sval = *(unsigned short *)buf;
+   else if (get_user(*sval, buf))
+   return -EFAULT;
+   return 0;
+}
 
 #ifdef USE_NONINTERLEAVE
 /* copy one channel block */
-static int emu8k_transfer_block(struct snd_emu8000 *emu, int offset, unsigned 
short *buf, int count)
+static int emu8k_transfer_block(struct snd_emu8000 *emu, int offset,
+   unsigned short *buf, int count, bool in_kernel)
 {
EMU8000_SMALW_WRITE(emu, offset);
while (count > 0) {
unsigned short sval;
CHECK_SCHEDULER();
-   if (get_user(sval, buf))
+   if (get_val(, buf, in_kernel))
return -EFAULT;
EMU8000_SMLD_WRITE(emu, sval);
buf++;
@@ -455,48 +467,18 @@ static int emu8k_pcm_copy(struct snd_pcm_substream *subs,
int i, err;
count /= rec->voices;
for (i = 0; i < rec->voices; i++) {
-   err = emu8k_transfer_block(emu, pos + 
rec->loop_start[i], buf, count);
+   err = emu8k_transfer_block(emu,
+  pos + rec->loop_start[i],
+  buf, count, in_kernel);
if (err < 0)
return err;
-   buf += count;
+   if (buf)
+   buf += count;
}
return 0;
} else {
-   return emu8k_transfer_block(emu, pos + rec->loop_start[voice], 
src, count);
-   }
-}
-
-/* make a channel block silence */
-static int emu8k_silence_block(struct snd_emu8000 *emu, int offset, int count)
-{
-   EMU8000_SMALW_WRITE(emu, offset);
-   while (count > 0) {
-   CHECK_SCHEDULER();
-   EMU8000_SMLD_WRITE(emu, 0);
-   count--;
-   }
-   return 0;
-}
-
-static int emu8k_pcm_silence(struct snd_pcm_substream *subs,
-int voice,
-snd_pcm_uframes_t pos,
-snd_pcm_uframes_t count)
-{
-   struct snd_emu8k_pcm *rec = subs->runtime->private_data;
-   struct snd_emu8000 *emu = rec->emu;
-
-   snd_emu8000_write_wait(emu, 1);
-   if (voice == -1 && rec->voices == 1)
-   voice = 0;
-   if (voice == -1) {
-   int err;
-   err = emu8k_silence_block(emu, pos + rec->loop_start[0], count 
/ 2);
-   if (err < 0)
-   return err;
-   return emu8k_silence_block(emu, pos + rec->loop_start[1], count 
/ 2);
-   } else {
-   return emu8k_silence_block(emu, pos + rec->loop_start[voice], 
count);
+   return emu8k_transfer_block(emu, pos + rec->loop_start[voice],
+   src, count, in_kernel);
}
 }
 
@@ -510,7 +492,8 @@ static int emu8k_pcm_copy(struct snd_pcm_substream *subs,
  int voice,
  snd_pcm_uframes_t pos,
  void __user *src,
- snd_pcm_uframes_t count)
+ snd_pcm_uframes_t count,
+ bool in_kernel)
 {
struct snd_emu8k_pcm *rec = subs->runtime->private_data;
struct snd_emu8000 *emu = rec->emu;
@@ -524,39 +507,18 @@ static int emu8k_pcm_copy(struct snd_pcm_substream *subs,
while (count-- > 0) {
unsigned short sval;
CHECK_SCHEDULER();
-   if (get_user(sval, buf))
+   if (get_val(, buf, in_kernel))
return -EFAULT;
EMU8000_SMLD_WRITE(emu, sval);
-   buf++;
+   if (buf)
+   buf++;
if (rec->voices > 1) {
CHECK_SCHEDULER();
-   if (get_user(sval, buf))
+   if (get_val(, buf, in_kernel))
return -EFAULT;
EMU8000_SMRD_WRITE(e

[PATCH 04/16] ALSA: es1938: Convert to copy_silence ops

2017-05-21 Thread Takashi Iwai
Replace the copy and the silence ops with the new merged ops.
It's used only for a capture stream (for some hardware workaround),
thus we need no silence operation but only to add the in_kernel
memcpy() handling.

Signed-off-by: Takashi Iwai <ti...@suse.de>
---
 sound/pci/es1938.c | 11 +++
 1 file changed, 7 insertions(+), 4 deletions(-)

diff --git a/sound/pci/es1938.c b/sound/pci/es1938.c
index e8d943071a8c..d79ac13d6f70 100644
--- a/sound/pci/es1938.c
+++ b/sound/pci/es1938.c
@@ -842,7 +842,8 @@ static int snd_es1938_capture_copy(struct snd_pcm_substream 
*substream,
   int channel,
   snd_pcm_uframes_t pos,
   void __user *dst,
-  snd_pcm_uframes_t count)
+  snd_pcm_uframes_t count,
+  bool in_kernel)
 {
struct snd_pcm_runtime *runtime = substream->runtime;
struct es1938 *chip = snd_pcm_substream_chip(substream);
@@ -850,8 +851,10 @@ static int snd_es1938_capture_copy(struct 
snd_pcm_substream *substream,
count <<= chip->dma1_shift;
if (snd_BUG_ON(pos + count > chip->dma1_size))
return -EINVAL;
-   if (pos + count < chip->dma1_size) {
-   if (copy_to_user(dst, runtime->dma_area + pos + 1, count))
+   if (in_kernel || pos + count < chip->dma1_size) {
+   if (in_kernel)
+   memcpy((void *)dst, runtime->dma_area + pos + 1, count);
+   else if (copy_to_user(dst, runtime->dma_area + pos + 1, count))
return -EFAULT;
} else {
if (copy_to_user(dst, runtime->dma_area + pos + 1, count - 1))
@@ -1012,7 +1015,7 @@ static const struct snd_pcm_ops snd_es1938_capture_ops = {
.prepare =  snd_es1938_capture_prepare,
.trigger =  snd_es1938_capture_trigger,
.pointer =  snd_es1938_capture_pointer,
-   .copy = snd_es1938_capture_copy,
+   .copy_silence = snd_es1938_capture_copy,
 };
 
 static int snd_es1938_new_pcm(struct es1938 *chip, int device)
-- 
2.13.0



[PATCH 10/16] ALSA: hdsp: Convert to copy_silence ops

2017-05-21 Thread Takashi Iwai
Replace the copy and the silence ops with the new merged ops.
The conversion is straightforward with standard helper functions.

Signed-off-by: Takashi Iwai <ti...@suse.de>
---
 sound/pci/rme9652/hdsp.c | 44 
 1 file changed, 20 insertions(+), 24 deletions(-)

diff --git a/sound/pci/rme9652/hdsp.c b/sound/pci/rme9652/hdsp.c
index fc0face6cdc6..5325e91fc3a8 100644
--- a/sound/pci/rme9652/hdsp.c
+++ b/sound/pci/rme9652/hdsp.c
@@ -3913,8 +3913,10 @@ static char *hdsp_channel_buffer_location(struct hdsp 
*hdsp,
return hdsp->playback_buffer + (mapped_channel * 
HDSP_CHANNEL_BUFFER_BYTES);
 }
 
-static int snd_hdsp_playback_copy(struct snd_pcm_substream *substream, int 
channel,
- snd_pcm_uframes_t pos, void __user *src, 
snd_pcm_uframes_t count)
+static int snd_hdsp_playback_copy(struct snd_pcm_substream *substream,
+ int channel, snd_pcm_uframes_t pos,
+ void __user *src, snd_pcm_uframes_t count,
+ bool in_kernel)
 {
struct hdsp *hdsp = snd_pcm_substream_chip(substream);
char *channel_buf;
@@ -3925,13 +3927,19 @@ static int snd_hdsp_playback_copy(struct 
snd_pcm_substream *substream, int chann
channel_buf = hdsp_channel_buffer_location (hdsp, 
substream->pstr->stream, channel);
if (snd_BUG_ON(!channel_buf))
return -EIO;
-   if (copy_from_user(channel_buf + pos * 4, src, count * 4))
+   if (!src)
+   memset(channel_buf + pos * 4, 0, count * 4);
+   else if (in_kernel)
+   memcpy(channel_buf + pos * 4, (void *)src, count * 4);
+   else if (copy_from_user(channel_buf + pos * 4, src, count * 4))
return -EFAULT;
-   return count;
+   return 0;
 }
 
-static int snd_hdsp_capture_copy(struct snd_pcm_substream *substream, int 
channel,
-snd_pcm_uframes_t pos, void __user *dst, 
snd_pcm_uframes_t count)
+static int snd_hdsp_capture_copy(struct snd_pcm_substream *substream,
+int channel, snd_pcm_uframes_t pos,
+void __user *dst, snd_pcm_uframes_t count,
+bool in_kernel)
 {
struct hdsp *hdsp = snd_pcm_substream_chip(substream);
char *channel_buf;
@@ -3942,22 +3950,11 @@ static int snd_hdsp_capture_copy(struct 
snd_pcm_substream *substream, int channe
channel_buf = hdsp_channel_buffer_location (hdsp, 
substream->pstr->stream, channel);
if (snd_BUG_ON(!channel_buf))
return -EIO;
-   if (copy_to_user(dst, channel_buf + pos * 4, count * 4))
+   if (in_kernel)
+   memcpy((void *)dst, channel_buf + pos * 4, count * 4);
+   else if (copy_to_user(dst, channel_buf + pos * 4, count * 4))
return -EFAULT;
-   return count;
-}
-
-static int snd_hdsp_hw_silence(struct snd_pcm_substream *substream, int 
channel,
- snd_pcm_uframes_t pos, snd_pcm_uframes_t 
count)
-{
-   struct hdsp *hdsp = snd_pcm_substream_chip(substream);
-   char *channel_buf;
-
-   channel_buf = hdsp_channel_buffer_location (hdsp, 
substream->pstr->stream, channel);
-   if (snd_BUG_ON(!channel_buf))
-   return -EIO;
-   memset(channel_buf + pos * 4, 0, count * 4);
-   return count;
+   return 0;
 }
 
 static int snd_hdsp_reset(struct snd_pcm_substream *substream)
@@ -4869,8 +4866,7 @@ static const struct snd_pcm_ops snd_hdsp_playback_ops = {
.prepare =  snd_hdsp_prepare,
.trigger =  snd_hdsp_trigger,
.pointer =  snd_hdsp_hw_pointer,
-   .copy = snd_hdsp_playback_copy,
-   .silence =  snd_hdsp_hw_silence,
+   .copy_silence = snd_hdsp_playback_copy,
 };
 
 static const struct snd_pcm_ops snd_hdsp_capture_ops = {
@@ -4881,7 +4877,7 @@ static const struct snd_pcm_ops snd_hdsp_capture_ops = {
.prepare =  snd_hdsp_prepare,
.trigger =  snd_hdsp_trigger,
.pointer =  snd_hdsp_hw_pointer,
-   .copy = snd_hdsp_capture_copy,
+   .copy_silence = snd_hdsp_capture_copy,
 };
 
 static int snd_hdsp_create_hwdep(struct snd_card *card, struct hdsp *hdsp)
-- 
2.13.0



[PATCH 02/16] ALSA: Update document about copy_silence PCM ops

2017-05-21 Thread Takashi Iwai
Signed-off-by: Takashi Iwai <ti...@suse.de>
---
 .../sound/kernel-api/writing-an-alsa-driver.rst| 110 -
 1 file changed, 63 insertions(+), 47 deletions(-)

diff --git a/Documentation/sound/kernel-api/writing-an-alsa-driver.rst 
b/Documentation/sound/kernel-api/writing-an-alsa-driver.rst
index 95c5443eff38..ebaf8b1e0079 100644
--- a/Documentation/sound/kernel-api/writing-an-alsa-driver.rst
+++ b/Documentation/sound/kernel-api/writing-an-alsa-driver.rst
@@ -2080,18 +2080,18 @@ sleeping poll threads, etc.
 
 This callback is also atomic as default.
 
-copy and silence callbacks
-~~
+copy_silence callback
+~
 
-These callbacks are not mandatory, and can be omitted in most cases.
-These callbacks are used when the hardware buffer cannot be in the
+This callback is not mandatory, and can be omitted in most cases.
+This callback is used when the hardware buffer cannot be in the
 normal memory space. Some chips have their own buffer on the hardware
 which is not mappable. In such a case, you have to transfer the data
 manually from the memory buffer to the hardware buffer. Or, if the
 buffer is non-contiguous on both physical and virtual memory spaces,
 these callbacks must be defined, too.
 
-If these two callbacks are defined, copy and set-silence operations
+If this callback is defined, copy and set-silence operations
 are done by them. The detailed will be described in the later section
 `Buffer and Memory Management`_.
 
@@ -3545,30 +3545,34 @@ Another case is when the chip uses a PCI memory-map 
region for the
 buffer instead of the host memory. In this case, mmap is available only
 on certain architectures like the Intel one. In non-mmap mode, the data
 cannot be transferred as in the normal way. Thus you need to define the
-``copy`` and ``silence`` callbacks as well, as in the cases above. The
+``copy_silence`` callback as well, as in the cases above. The
 examples are found in ``rme32.c`` and ``rme96.c``.
 
-The implementation of the ``copy`` and ``silence`` callbacks depends
+The implementation of the ``copy_silence`` callback depends
 upon whether the hardware supports interleaved or non-interleaved
-samples. The ``copy`` callback is defined like below, a bit
+samples. The ``copy_silence`` callback is defined like below, a bit
 differently depending whether the direction is playback or capture:
 
 ::
 
   static int playback_copy(struct snd_pcm_substream *substream, int channel,
-   snd_pcm_uframes_t pos, void *src, snd_pcm_uframes_t count);
+   snd_pcm_uframes_t pos, void __user *src,
+  snd_pcm_uframes_t count, bool in_kernel);
   static int capture_copy(struct snd_pcm_substream *substream, int channel,
-   snd_pcm_uframes_t pos, void *dst, snd_pcm_uframes_t count);
+   snd_pcm_uframes_t pos, void __user *dst,
+  snd_pcm_uframes_t count, bool in_kernel);
 
 In the case of interleaved samples, the second argument (``channel``) is
-not used. The third argument (``pos``) points the current position
-offset in frames.
+not used, and -1 is passed. The third argument (``pos``) points the
+current position offset in frames.
 
 The meaning of the fourth argument is different between playback and
 capture. For playback, it holds the source data pointer, and for
 capture, it's the destination data pointer.
 
-The last argument is the number of frames to be copied.
+The fifth argument is the number of frames to be copied.
+And the last argument indicates whether the passed buffer pointer is in
+user-space or in kernel-space.  The copy operation depends on this.
 
 What you have to do in this callback is again different between playback
 and capture directions. In the playback case, you copy the given amount
@@ -3578,52 +3582,64 @@ way, the copy would be like:
 
 ::
 
-  my_memcpy(my_buffer + frames_to_bytes(runtime, pos), src,
-frames_to_bytes(runtime, count));
-
-For the capture direction, you copy the given amount of data (``count``)
-at the specified offset (``pos``) on the hardware buffer to the
-specified pointer (``dst``).
-
-::
+  if (!src)
+  my_memset(my_buffer + frames_to_bytes(runtime, pos), 0,
+frames_to_bytes(runtime, count));
+  else if (in_kernel)
+  memcpy_toio(my_buffer + frames_to_bytes(runtime, pos),
+  (void *)src, frames_to_bytes(runtime, count));
+  else if (copy_from_user_toio(my_buffer + frames_to_bytes(runtime, pos),
+   src, frames_to_bytes(runtime, count)))
+  return -EFAULT;
+  return 0;
 
-  my_memcpy(dst, my_buffer + frames_to_bytes(runtime, pos),
-frames_to_bytes(runtime, count));
+Here we prepared three different memory operations operations.
 
-Note that both the position and the amount of data are given in frames.
+The first one, with the NULL ``src`` pointer, is for silencing the
+buffer. In this case, we clear the s

[PATCH 08/16] ALSA: rme96: Convert to copy_silence ops

2017-05-21 Thread Takashi Iwai
Replace the copy and the silence ops with the new merged ops.
The conversion is straightforward with standard helper functions.

Signed-off-by: Takashi Iwai <ti...@suse.de>
---
 sound/pci/rme96.c | 52 ++--
 1 file changed, 26 insertions(+), 26 deletions(-)

diff --git a/sound/pci/rme96.c b/sound/pci/rme96.c
index 05b9da30990d..2161f6aad532 100644
--- a/sound/pci/rme96.c
+++ b/sound/pci/rme96.c
@@ -326,31 +326,25 @@ snd_rme96_capture_ptr(struct rme96 *rme96)
 }
 
 static int
-snd_rme96_playback_silence(struct snd_pcm_substream *substream,
-  int channel, /* not used (interleaved data) */
-  snd_pcm_uframes_t pos,
-  snd_pcm_uframes_t count)
-{
-   struct rme96 *rme96 = snd_pcm_substream_chip(substream);
-   count <<= rme96->playback_frlog;
-   pos <<= rme96->playback_frlog;
-   memset_io(rme96->iobase + RME96_IO_PLAY_BUFFER + pos,
- 0, count);
-   return 0;
-}
-
-static int
 snd_rme96_playback_copy(struct snd_pcm_substream *substream,
int channel, /* not used (interleaved data) */
snd_pcm_uframes_t pos,
void __user *src,
-   snd_pcm_uframes_t count)
+   snd_pcm_uframes_t count,
+   bool in_kernel)
 {
struct rme96 *rme96 = snd_pcm_substream_chip(substream);
count <<= rme96->playback_frlog;
pos <<= rme96->playback_frlog;
-   return copy_from_user_toio(rme96->iobase + RME96_IO_PLAY_BUFFER + pos, 
src,
-  count);
+   if (!src)
+   memset_io(rme96->iobase + RME96_IO_PLAY_BUFFER + pos, 0, count);
+   else if (in_kernel)
+   memcpy_toio(rme96->iobase + RME96_IO_PLAY_BUFFER + pos,
+   (void *)src, count);
+   else if (copy_from_user_toio(rme96->iobase + RME96_IO_PLAY_BUFFER + pos,
+src, count))
+   return -EFAULT;
+   return 0;
 }
 
 static int
@@ -358,13 +352,21 @@ snd_rme96_capture_copy(struct snd_pcm_substream 
*substream,
   int channel, /* not used (interleaved data) */
   snd_pcm_uframes_t pos,
   void __user *dst,
-  snd_pcm_uframes_t count)
+  snd_pcm_uframes_t count,
+  bool in_kernel)
 {
struct rme96 *rme96 = snd_pcm_substream_chip(substream);
count <<= rme96->capture_frlog;
pos <<= rme96->capture_frlog;
-   return copy_to_user_fromio(dst, rme96->iobase + RME96_IO_REC_BUFFER + 
pos,
-  count);
+   if (in_kernel)
+   memcpy_fromio((void *)dst,
+ rme96->iobase + RME96_IO_REC_BUFFER + pos,
+ count);
+   else if (copy_to_user_fromio(dst,
+rme96->iobase + RME96_IO_REC_BUFFER + pos,
+count))
+   return -EFAULT;
+   return 0;
 }
 
 /*
@@ -1513,8 +1515,7 @@ static const struct snd_pcm_ops 
snd_rme96_playback_spdif_ops = {
.prepare =  snd_rme96_playback_prepare,
.trigger =  snd_rme96_playback_trigger,
.pointer =  snd_rme96_playback_pointer,
-   .copy = snd_rme96_playback_copy,
-   .silence =  snd_rme96_playback_silence,
+   .copy_silence = snd_rme96_playback_copy,
.mmap = snd_pcm_lib_mmap_iomem,
 };
 
@@ -1526,7 +1527,7 @@ static const struct snd_pcm_ops 
snd_rme96_capture_spdif_ops = {
.prepare =  snd_rme96_capture_prepare,
.trigger =  snd_rme96_capture_trigger,
.pointer =  snd_rme96_capture_pointer,
-   .copy = snd_rme96_capture_copy,
+   .copy_silence = snd_rme96_capture_copy,
.mmap = snd_pcm_lib_mmap_iomem,
 };
 
@@ -1538,8 +1539,7 @@ static const struct snd_pcm_ops 
snd_rme96_playback_adat_ops = {
.prepare =  snd_rme96_playback_prepare,
.trigger =  snd_rme96_playback_trigger,
.pointer =  snd_rme96_playback_pointer,
-   .copy = snd_rme96_playback_copy,
-   .silence =  snd_rme96_playback_silence,
+   .copy_silence = snd_rme96_playback_copy,
.mmap = snd_pcm_lib_mmap_iomem,
 };
 
@@ -1551,7 +1551,7 @@ static const struct snd_pcm_ops 
snd_rme96_capture_adat_ops = {
.prepare =  snd_rme96_capture_prepare,
.trigger =  snd_rme96_capture_trigger,
.pointer =  snd_rme96_capture_pointer,
-   .copy = snd_rme96_capture_copy,
+   .copy_silence = snd_rme96_capture_copy,
.mmap = snd_pcm_lib_mmap_iomem,
 };
 
-- 
2.13.0



[PATCH 06/16] ALSA: nm256: Convert to copy_silence ops

2017-05-21 Thread Takashi Iwai
Replace the copy and the silence ops with the new merged ops.
The conversion is straightforward with standard helper functions.

Signed-off-by: Takashi Iwai <ti...@suse.de>
---
 sound/pci/nm256/nm256.c | 35 ++-
 1 file changed, 14 insertions(+), 21 deletions(-)

diff --git a/sound/pci/nm256/nm256.c b/sound/pci/nm256/nm256.c
index 103fe311e5a9..d8e765f7e758 100644
--- a/sound/pci/nm256/nm256.c
+++ b/sound/pci/nm256/nm256.c
@@ -694,31 +694,22 @@ snd_nm256_capture_pointer(struct snd_pcm_substream 
*substream)
  * silence / copy for playback
  */
 static int
-snd_nm256_playback_silence(struct snd_pcm_substream *substream,
-  int channel, /* not used (interleaved data) */
-  snd_pcm_uframes_t pos,
-  snd_pcm_uframes_t count)
-{
-   struct snd_pcm_runtime *runtime = substream->runtime;
-   struct nm256_stream *s = runtime->private_data;
-   count = frames_to_bytes(runtime, count);
-   pos = frames_to_bytes(runtime, pos);
-   memset_io(s->bufptr + pos, 0, count);
-   return 0;
-}
-
-static int
 snd_nm256_playback_copy(struct snd_pcm_substream *substream,
int channel, /* not used (interleaved data) */
snd_pcm_uframes_t pos,
void __user *src,
-   snd_pcm_uframes_t count)
+   snd_pcm_uframes_t count,
+   bool in_kernel)
 {
struct snd_pcm_runtime *runtime = substream->runtime;
struct nm256_stream *s = runtime->private_data;
count = frames_to_bytes(runtime, count);
pos = frames_to_bytes(runtime, pos);
-   if (copy_from_user_toio(s->bufptr + pos, src, count))
+   if (!src)
+   memset_io(s->bufptr + pos, 0, count);
+   else if (in_kernel)
+   memcpy_toio(s->bufptr + pos, (void *)src, count);
+   else if (copy_from_user_toio(s->bufptr + pos, src, count))
return -EFAULT;
return 0;
 }
@@ -731,13 +722,16 @@ snd_nm256_capture_copy(struct snd_pcm_substream 
*substream,
   int channel, /* not used (interleaved data) */
   snd_pcm_uframes_t pos,
   void __user *dst,
-  snd_pcm_uframes_t count)
+  snd_pcm_uframes_t count,
+  bool in_kernel)
 {
struct snd_pcm_runtime *runtime = substream->runtime;
struct nm256_stream *s = runtime->private_data;
count = frames_to_bytes(runtime, count);
pos = frames_to_bytes(runtime, pos);
-   if (copy_to_user_fromio(dst, s->bufptr + pos, count))
+   if (in_kernel)
+   memcpy_fromio((void *)dst, s->bufptr + pos, count);
+   else if (copy_to_user_fromio(dst, s->bufptr + pos, count))
return -EFAULT;
return 0;
 }
@@ -911,8 +905,7 @@ static const struct snd_pcm_ops snd_nm256_playback_ops = {
.trigger =  snd_nm256_playback_trigger,
.pointer =  snd_nm256_playback_pointer,
 #ifndef __i386__
-   .copy = snd_nm256_playback_copy,
-   .silence =  snd_nm256_playback_silence,
+   .copy_silence = snd_nm256_playback_copy,
 #endif
.mmap = snd_pcm_lib_mmap_iomem,
 };
@@ -926,7 +919,7 @@ static const struct snd_pcm_ops snd_nm256_capture_ops = {
.trigger =  snd_nm256_capture_trigger,
.pointer =  snd_nm256_capture_pointer,
 #ifndef __i386__
-   .copy = snd_nm256_capture_copy,
+   .copy_silence = snd_nm256_capture_copy,
 #endif
.mmap = snd_pcm_lib_mmap_iomem,
 };
-- 
2.13.0



[PATCH 09/16] ALSA: rme9652: Convert to copy_silence ops

2017-05-21 Thread Takashi Iwai
Replace the copy and the silence ops with the new merged ops.
The conversion is straightforward with standard helper functions.

Signed-off-by: Takashi Iwai <ti...@suse.de>
---
 sound/pci/rme9652/rme9652.c | 46 -
 1 file changed, 20 insertions(+), 26 deletions(-)

diff --git a/sound/pci/rme9652/rme9652.c b/sound/pci/rme9652/rme9652.c
index 55172c689991..ce9faa32c7ed 100644
--- a/sound/pci/rme9652/rme9652.c
+++ b/sound/pci/rme9652/rme9652.c
@@ -1883,8 +1883,10 @@ static char *rme9652_channel_buffer_location(struct 
snd_rme9652 *rme9652,
}
 }
 
-static int snd_rme9652_playback_copy(struct snd_pcm_substream *substream, int 
channel,
-snd_pcm_uframes_t pos, void __user *src, 
snd_pcm_uframes_t count)
+static int snd_rme9652_playback_copy(struct snd_pcm_substream *substream,
+int channel, snd_pcm_uframes_t pos,
+void __user *src, snd_pcm_uframes_t count,
+bool in_kernel)
 {
struct snd_rme9652 *rme9652 = snd_pcm_substream_chip(substream);
char *channel_buf;
@@ -1897,13 +1899,19 @@ static int snd_rme9652_playback_copy(struct 
snd_pcm_substream *substream, int ch
   channel);
if (snd_BUG_ON(!channel_buf))
return -EIO;
-   if (copy_from_user(channel_buf + pos * 4, src, count * 4))
+   if (!src)
+   memset(channel_buf + pos * 4, 0, count * 4);
+   else if (in_kernel)
+   memcpy(channel_buf + pos * 4, (void *)src, count * 4);
+   else if (copy_from_user(channel_buf + pos * 4, src, count * 4))
return -EFAULT;
-   return count;
+   return 0;
 }
 
-static int snd_rme9652_capture_copy(struct snd_pcm_substream *substream, int 
channel,
-   snd_pcm_uframes_t pos, void __user *dst, 
snd_pcm_uframes_t count)
+static int snd_rme9652_capture_copy(struct snd_pcm_substream *substream,
+   int channel, snd_pcm_uframes_t pos,
+   void __user *dst, snd_pcm_uframes_t count,
+   bool in_kernel)
 {
struct snd_rme9652 *rme9652 = snd_pcm_substream_chip(substream);
char *channel_buf;
@@ -1916,24 +1924,11 @@ static int snd_rme9652_capture_copy(struct 
snd_pcm_substream *substream, int cha
   channel);
if (snd_BUG_ON(!channel_buf))
return -EIO;
-   if (copy_to_user(dst, channel_buf + pos * 4, count * 4))
+   if (in_kernel)
+   memcpy((void *)dst, channel_buf + pos * 4, count * 4);
+   else if (copy_to_user(dst, channel_buf + pos * 4, count * 4))
return -EFAULT;
-   return count;
-}
-
-static int snd_rme9652_hw_silence(struct snd_pcm_substream *substream, int 
channel,
- snd_pcm_uframes_t pos, snd_pcm_uframes_t 
count)
-{
-   struct snd_rme9652 *rme9652 = snd_pcm_substream_chip(substream);
-   char *channel_buf;
-
-   channel_buf = rme9652_channel_buffer_location (rme9652,
-  substream->pstr->stream,
-  channel);
-   if (snd_BUG_ON(!channel_buf))
-   return -EIO;
-   memset(channel_buf + pos * 4, 0, count * 4);
-   return count;
+   return 0;
 }
 
 static int snd_rme9652_reset(struct snd_pcm_substream *substream)
@@ -2376,8 +2371,7 @@ static const struct snd_pcm_ops snd_rme9652_playback_ops 
= {
.prepare =  snd_rme9652_prepare,
.trigger =  snd_rme9652_trigger,
.pointer =  snd_rme9652_hw_pointer,
-   .copy = snd_rme9652_playback_copy,
-   .silence =  snd_rme9652_hw_silence,
+   .copy_silence = snd_rme9652_playback_copy,
 };
 
 static const struct snd_pcm_ops snd_rme9652_capture_ops = {
@@ -2388,7 +2382,7 @@ static const struct snd_pcm_ops snd_rme9652_capture_ops = 
{
.prepare =  snd_rme9652_prepare,
.trigger =  snd_rme9652_trigger,
.pointer =  snd_rme9652_hw_pointer,
-   .copy = snd_rme9652_capture_copy,
+   .copy_silence = snd_rme9652_capture_copy,
 };
 
 static int snd_rme9652_create_pcm(struct snd_card *card,
-- 
2.13.0



[PATCH 05/16] ALSA: korg1212: Convert to copy_silence ops

2017-05-21 Thread Takashi Iwai
Replace the copy and the silence ops with the new merged ops.
The redundant function calls are reduced and the copy/silence are
handled directly in callback functions now.

Signed-off-by: Takashi Iwai <ti...@suse.de>
---
 sound/pci/korg1212/korg1212.c | 128 --
 1 file changed, 36 insertions(+), 92 deletions(-)

diff --git a/sound/pci/korg1212/korg1212.c b/sound/pci/korg1212/korg1212.c
index 1e25095fd144..865ff553dc87 100644
--- a/sound/pci/korg1212/korg1212.c
+++ b/sound/pci/korg1212/korg1212.c
@@ -1273,43 +1273,24 @@ static struct snd_pcm_hardware 
snd_korg1212_capture_info =
 .fifo_size =  0,
 };
 
-static int snd_korg1212_silence(struct snd_korg1212 *korg1212, int pos, int 
count, int offset, int size)
-{
-   struct KorgAudioFrame * dst =  korg1212->playDataBufsPtr[0].bufferData 
+ pos;
-   int i;
-
-   K1212_DEBUG_PRINTK_VERBOSE("K1212_DEBUG: snd_korg1212_silence pos=%d 
offset=%d size=%d count=%d\n",
-  pos, offset, size, count);
-   if (snd_BUG_ON(pos + count > K1212_MAX_SAMPLES))
-   return -EINVAL;
-
-   for (i=0; i < count; i++) {
-#if K1212_DEBUG_LEVEL > 0
-   if ( (void *) dst < (void *) korg1212->playDataBufsPtr ||
-(void *) dst > (void *) 
korg1212->playDataBufsPtr[8].bufferData ) {
-   printk(KERN_DEBUG "K1212_DEBUG: snd_korg1212_silence 
KERNEL EFAULT dst=%p iter=%d\n",
-  dst, i);
-   return -EFAULT;
-   }
-#endif
-   memset((void*) dst + offset, 0, size);
-   dst++;
-   }
-
-   return 0;
-}
-
-static int snd_korg1212_copy_to(struct snd_korg1212 *korg1212, void __user 
*dst, int pos, int count, int offset, int size)
+static int snd_korg1212_capture_copy(struct snd_pcm_substream *substream,
+int channel,
+snd_pcm_uframes_t pos,
+void __user *dst,
+snd_pcm_uframes_t count,
+bool in_kernel)
 {
+   struct snd_korg1212 *korg1212 = snd_pcm_substream_chip(substream);
struct KorgAudioFrame * src =  
korg1212->recordDataBufsPtr[0].bufferData + pos;
-   int i, rc;
+   int size, i;
 
-   K1212_DEBUG_PRINTK_VERBOSE("K1212_DEBUG: snd_korg1212_copy_to pos=%d 
offset=%d size=%d\n",
-  pos, offset, size);
+   size = korg1212->channels * 2;
+   K1212_DEBUG_PRINTK_VERBOSE("K1212_DEBUG: snd_korg1212_copy_to pos=%ld 
size=%d\n",
+  pos, size);
if (snd_BUG_ON(pos + count > K1212_MAX_SAMPLES))
return -EINVAL;
 
-   for (i=0; i < count; i++) {
+   for (i = 0; i < count; i++) {
 #if K1212_DEBUG_LEVEL > 0
if ( (void *) src < (void *) korg1212->recordDataBufsPtr ||
 (void *) src > (void *) 
korg1212->recordDataBufsPtr[8].bufferData ) {
@@ -1317,11 +1298,10 @@ static int snd_korg1212_copy_to(struct snd_korg1212 
*korg1212, void __user *dst,
return -EFAULT;
}
 #endif
-   rc = copy_to_user(dst + offset, src, size);
-   if (rc) {
-   K1212_DEBUG_PRINTK("K1212_DEBUG: snd_korg1212_copy_to 
USER EFAULT src=%p dst=%p iter=%d\n", src, dst, i);
+   if (in_kernel)
+   memcpy((char *)dst, src, size);
+   else if (copy_to_user(dst, src, size))
return -EFAULT;
-   }
src++;
dst += size;
}
@@ -1329,18 +1309,25 @@ static int snd_korg1212_copy_to(struct snd_korg1212 
*korg1212, void __user *dst,
return 0;
 }
 
-static int snd_korg1212_copy_from(struct snd_korg1212 *korg1212, void __user 
*src, int pos, int count, int offset, int size)
+static int snd_korg1212_playback_copy(struct snd_pcm_substream *substream,
+ int channel,
+ snd_pcm_uframes_t pos,
+ void __user *src,
+ snd_pcm_uframes_t count,
+ bool in_kernel)
 {
+   struct snd_korg1212 *korg1212 = snd_pcm_substream_chip(substream);
struct KorgAudioFrame * dst =  korg1212->playDataBufsPtr[0].bufferData 
+ pos;
-   int i, rc;
+   int size, i;
 
-   K1212_DEBUG_PRINTK_VERBOSE("K1212_DEBUG: snd_korg1212_copy_from pos=%d 
offset=%d size=%d count=%d\n",
-  pos, offset, size, count);
+   size = korg1212->channels * 2;
+   K1212_DEBUG_PRINTK_VERBOSE("K1212_DEBUG: snd_korg1212_copy_from pos=%ld 
s

[PATCH 11/16] ALSA: gus: Convert to copy_silence ops

2017-05-21 Thread Takashi Iwai
Replace the copy and the silence ops with the new merged ops.
The conversion is straightforward with standard helper functions.

Signed-off-by: Takashi Iwai <ti...@suse.de>
---
 sound/isa/gus/gus_pcm.c | 43 +--
 1 file changed, 9 insertions(+), 34 deletions(-)

diff --git a/sound/isa/gus/gus_pcm.c b/sound/isa/gus/gus_pcm.c
index 33c1891f469a..c541370d3d76 100644
--- a/sound/isa/gus/gus_pcm.c
+++ b/sound/isa/gus/gus_pcm.c
@@ -359,7 +359,8 @@ static int snd_gf1_pcm_playback_copy(struct 
snd_pcm_substream *substream,
 int voice,
 snd_pcm_uframes_t pos,
 void __user *src,
-snd_pcm_uframes_t count)
+snd_pcm_uframes_t count,
+bool in_kernel)
 {
struct snd_pcm_runtime *runtime = substream->runtime;
struct gus_pcm_private *pcmp = runtime->private_data;
@@ -371,7 +372,12 @@ static int snd_gf1_pcm_playback_copy(struct 
snd_pcm_substream *substream,
return -EIO;
if (snd_BUG_ON(bpos + len > pcmp->dma_size))
return -EIO;
-   if (copy_from_user(runtime->dma_area + bpos, src, len))
+   if (!src)
+   snd_pcm_format_set_silence(runtime->format,
+  runtime->dma_area + bpos, count);
+   else if (in_kernel)
+   memcpy(runtime->dma_area + bpos, (void *)src, len);
+   else if (copy_from_user(runtime->dma_area + bpos, src, len))
return -EFAULT;
if (snd_gf1_pcm_use_dma && len > 32) {
return snd_gf1_pcm_block_change(substream, bpos, pcmp->memory + 
bpos, len);
@@ -387,36 +393,6 @@ static int snd_gf1_pcm_playback_copy(struct 
snd_pcm_substream *substream,
return 0;
 }
 
-static int snd_gf1_pcm_playback_silence(struct snd_pcm_substream *substream,
-   int voice,
-   snd_pcm_uframes_t pos,
-   snd_pcm_uframes_t count)
-{
-   struct snd_pcm_runtime *runtime = substream->runtime;
-   struct gus_pcm_private *pcmp = runtime->private_data;
-   unsigned int bpos, len;
-   
-   bpos = samples_to_bytes(runtime, pos) + (voice * (pcmp->dma_size / 2));
-   len = samples_to_bytes(runtime, count);
-   if (snd_BUG_ON(bpos > pcmp->dma_size))
-   return -EIO;
-   if (snd_BUG_ON(bpos + len > pcmp->dma_size))
-   return -EIO;
-   snd_pcm_format_set_silence(runtime->format, runtime->dma_area + bpos, 
count);
-   if (snd_gf1_pcm_use_dma && len > 32) {
-   return snd_gf1_pcm_block_change(substream, bpos, pcmp->memory + 
bpos, len);
-   } else {
-   struct snd_gus_card *gus = pcmp->gus;
-   int err, w16, invert;
-
-   w16 = (snd_pcm_format_width(runtime->format) == 16);
-   invert = snd_pcm_format_unsigned(runtime->format);
-   if ((err = snd_gf1_pcm_poke_block(gus, runtime->dma_area + 
bpos, pcmp->memory + bpos, len, w16, invert)) < 0)
-   return err;
-   }
-   return 0;
-}
-
 static int snd_gf1_pcm_playback_hw_params(struct snd_pcm_substream *substream,
  struct snd_pcm_hw_params *hw_params)
 {
@@ -836,8 +812,7 @@ static struct snd_pcm_ops snd_gf1_pcm_playback_ops = {
.prepare =  snd_gf1_pcm_playback_prepare,
.trigger =  snd_gf1_pcm_playback_trigger,
.pointer =  snd_gf1_pcm_playback_pointer,
-   .copy = snd_gf1_pcm_playback_copy,
-   .silence =  snd_gf1_pcm_playback_silence,
+   .copy_silence = snd_gf1_pcm_playback_copy,
 };
 
 static struct snd_pcm_ops snd_gf1_pcm_capture_ops = {
-- 
2.13.0



[PATCH 13/16] ALSA: sh: Convert to copy_silence ops

2017-05-21 Thread Takashi Iwai
Replace the copy and the silence ops with the new merged ops.
A straightforward conversion with standard helper functions.

Signed-off-by: Takashi Iwai <ti...@suse.de>
---
 sound/sh/sh_dac_audio.c | 40 +---
 1 file changed, 9 insertions(+), 31 deletions(-)

diff --git a/sound/sh/sh_dac_audio.c b/sound/sh/sh_dac_audio.c
index 461b310c7872..a4014a4548d0 100644
--- a/sound/sh/sh_dac_audio.c
+++ b/sound/sh/sh_dac_audio.c
@@ -185,7 +185,8 @@ static int snd_sh_dac_pcm_trigger(struct snd_pcm_substream 
*substream, int cmd)
 }
 
 static int snd_sh_dac_pcm_copy(struct snd_pcm_substream *substream, int 
channel,
-   snd_pcm_uframes_t pos, void __user *src, snd_pcm_uframes_t count)
+  snd_pcm_uframes_t pos, void __user *src,
+  snd_pcm_uframes_t count, bool in_kernel)
 {
/* channel is not used (interleaved data) */
struct snd_sh_dac *chip = snd_pcm_substream_chip(substream);
@@ -199,34 +200,12 @@ static int snd_sh_dac_pcm_copy(struct snd_pcm_substream 
*substream, int channel,
if (!count)
return 0;
 
-   memcpy_toio(chip->data_buffer + b_pos, src, b_count);
-   chip->buffer_end = chip->data_buffer + b_pos + b_count;
-
-   if (chip->empty) {
-   chip->empty = 0;
-   dac_audio_start_timer(chip);
-   }
-
-   return 0;
-}
-
-static int snd_sh_dac_pcm_silence(struct snd_pcm_substream *substream,
- int channel, snd_pcm_uframes_t pos,
- snd_pcm_uframes_t count)
-{
-   /* channel is not used (interleaved data) */
-   struct snd_sh_dac *chip = snd_pcm_substream_chip(substream);
-   struct snd_pcm_runtime *runtime = substream->runtime;
-   ssize_t b_count = frames_to_bytes(runtime , count);
-   ssize_t b_pos = frames_to_bytes(runtime , pos);
-
-   if (count < 0)
-   return -EINVAL;
-
-   if (!count)
-   return 0;
-
-   memset_io(chip->data_buffer + b_pos, 0, b_count);
+   if (!src)
+   memset_io(chip->data_buffer + b_pos, 0, b_count);
+   else if (in_kernel)
+   memcpy_toio(chip->data_buffer + b_pos, (void *)src, b_count);
+   else if (copy_from_user_toio(chip->data_buffer + b_pos, src, b_count))
+   return -EFAULT;
chip->buffer_end = chip->data_buffer + b_pos + b_count;
 
if (chip->empty) {
@@ -256,8 +235,7 @@ static struct snd_pcm_ops snd_sh_dac_pcm_ops = {
.prepare= snd_sh_dac_pcm_prepare,
.trigger= snd_sh_dac_pcm_trigger,
.pointer= snd_sh_dac_pcm_pointer,
-   .copy   = snd_sh_dac_pcm_copy,
-   .silence= snd_sh_dac_pcm_silence,
+   .copy_silence   = snd_sh_dac_pcm_copy,
.mmap   = snd_pcm_lib_mmap_iomem,
 };
 
-- 
2.13.0



[PATCH 07/16] ALSA: rme32: Convert to copy_silence ops

2017-05-21 Thread Takashi Iwai
Replace the copy and the silence ops with the new merged ops.
The conversion is straightforward with standard helper functions.

Signed-off-by: Takashi Iwai <ti...@suse.de>
---
 sound/pci/rme32.c | 49 -
 1 file changed, 24 insertions(+), 25 deletions(-)

diff --git a/sound/pci/rme32.c b/sound/pci/rme32.c
index 96d15db65dfd..d2b4a3ef0bd3 100644
--- a/sound/pci/rme32.c
+++ b/sound/pci/rme32.c
@@ -253,41 +253,42 @@ static inline unsigned int snd_rme32_pcm_byteptr(struct 
rme32 * rme32)
& RME32_RCR_AUDIO_ADDR_MASK);
 }
 
-/* silence callback for halfduplex mode */
-static int snd_rme32_playback_silence(struct snd_pcm_substream *substream, int 
channel,/* not used (interleaved data) */
- snd_pcm_uframes_t pos,
- snd_pcm_uframes_t count)
-{
-   struct rme32 *rme32 = snd_pcm_substream_chip(substream);
-   count <<= rme32->playback_frlog;
-   pos <<= rme32->playback_frlog;
-   memset_io(rme32->iobase + RME32_IO_DATA_BUFFER + pos, 0, count);
-   return 0;
-}
-
 /* copy callback for halfduplex mode */
-static int snd_rme32_playback_copy(struct snd_pcm_substream *substream, int 
channel,   /* not used (interleaved data) */
+static int snd_rme32_playback_copy(struct snd_pcm_substream *substream,
+  int channel, /* not used (interleaved data) 
*/
   snd_pcm_uframes_t pos,
-  void __user *src, snd_pcm_uframes_t count)
+  void __user *src, snd_pcm_uframes_t count,
+  bool in_kernel)
 {
struct rme32 *rme32 = snd_pcm_substream_chip(substream);
count <<= rme32->playback_frlog;
pos <<= rme32->playback_frlog;
-   if (copy_from_user_toio(rme32->iobase + RME32_IO_DATA_BUFFER + pos,
-   src, count))
+   if (!src)
+   memset_io(rme32->iobase + RME32_IO_DATA_BUFFER + pos, 0, count);
+   else if (in_kernel)
+   memcpy_toio(rme32->iobase + RME32_IO_DATA_BUFFER + pos,
+   (void *)src, count);
+   else if (copy_from_user_toio(rme32->iobase + RME32_IO_DATA_BUFFER + pos,
+src, count))
return -EFAULT;
return 0;
 }
 
 /* copy callback for halfduplex mode */
-static int snd_rme32_capture_copy(struct snd_pcm_substream *substream, int 
channel,/* not used (interleaved data) */
+static int snd_rme32_capture_copy(struct snd_pcm_substream *substream,
+ int channel,  /* not used (interleaved data) 
*/
  snd_pcm_uframes_t pos,
- void __user *dst, snd_pcm_uframes_t count)
+ void __user *dst, snd_pcm_uframes_t count,
+ bool in_kernel)
 {
struct rme32 *rme32 = snd_pcm_substream_chip(substream);
count <<= rme32->capture_frlog;
pos <<= rme32->capture_frlog;
-   if (copy_to_user_fromio(dst,
+   if (in_kernel)
+   memcpy_fromio((void *)dst,
+ rme32->iobase + RME32_IO_DATA_BUFFER + pos,
+ count);
+   else if (copy_to_user_fromio(dst,
rme32->iobase + RME32_IO_DATA_BUFFER + pos,
count))
return -EFAULT;
@@ -1205,8 +1206,7 @@ static const struct snd_pcm_ops 
snd_rme32_playback_spdif_ops = {
.prepare =  snd_rme32_playback_prepare,
.trigger =  snd_rme32_pcm_trigger,
.pointer =  snd_rme32_playback_pointer,
-   .copy = snd_rme32_playback_copy,
-   .silence =  snd_rme32_playback_silence,
+   .copy_silence = snd_rme32_playback_copy,
.mmap = snd_pcm_lib_mmap_iomem,
 };
 
@@ -1219,7 +1219,7 @@ static const struct snd_pcm_ops 
snd_rme32_capture_spdif_ops = {
.prepare =  snd_rme32_capture_prepare,
.trigger =  snd_rme32_pcm_trigger,
.pointer =  snd_rme32_capture_pointer,
-   .copy = snd_rme32_capture_copy,
+   .copy_silence = snd_rme32_capture_copy,
.mmap = snd_pcm_lib_mmap_iomem,
 };
 
@@ -1231,8 +1231,7 @@ static const struct snd_pcm_ops 
snd_rme32_playback_adat_ops = {
.prepare =  snd_rme32_playback_prepare,
.trigger =  snd_rme32_pcm_trigger,
.pointer =  snd_rme32_playback_pointer,
-   .copy = snd_rme32_playback_copy,
-   .silence =  snd_rme32_playback_silence,
+   .copy_silence = snd_rme32_playback_copy,
.mmap = snd_pcm_lib_mmap_iomem,
 };
 
@@ -1244,7 +1243,7 @@ static const struct snd_pcm_ops 
snd_rme32_capture_adat_ops = {
.pr

[PATCH 03/16] ALSA: dummy: Convert to copy_silence ops

2017-05-21 Thread Takashi Iwai
It's a dummy ops, so just replacing it.

Signed-off-by: Takashi Iwai <ti...@suse.de>
---
 sound/drivers/dummy.c | 13 +++--
 1 file changed, 3 insertions(+), 10 deletions(-)

diff --git a/sound/drivers/dummy.c b/sound/drivers/dummy.c
index 172dacd925f5..68519689a9ea 100644
--- a/sound/drivers/dummy.c
+++ b/sound/drivers/dummy.c
@@ -645,14 +645,8 @@ static int alloc_fake_buffer(void)
 
 static int dummy_pcm_copy(struct snd_pcm_substream *substream,
  int channel, snd_pcm_uframes_t pos,
- void __user *dst, snd_pcm_uframes_t count)
-{
-   return 0; /* do nothing */
-}
-
-static int dummy_pcm_silence(struct snd_pcm_substream *substream,
-int channel, snd_pcm_uframes_t pos,
-snd_pcm_uframes_t count)
+ void __user *dst, snd_pcm_uframes_t count,
+ bool in_kernel)
 {
return 0; /* do nothing */
 }
@@ -683,8 +677,7 @@ static struct snd_pcm_ops dummy_pcm_ops_no_buf = {
.prepare =  dummy_pcm_prepare,
.trigger =  dummy_pcm_trigger,
.pointer =  dummy_pcm_pointer,
-   .copy = dummy_pcm_copy,
-   .silence =  dummy_pcm_silence,
+   .copy_silence = dummy_pcm_copy,
.page = dummy_pcm_page,
 };
 
-- 
2.13.0



[PATCH 00/16] ALSA: Convert to new copy_silence PCM ops

2017-05-21 Thread Takashi Iwai
Hi,

this is a part of the previous RFC patchset, and it's preliminary for
eliminating set_fs() usages in the rest ALSA codes.  This patchset
itself converts the existing copy and silence PCM ops to a new single
copy_silence ops.  The new callback takes in_kernel flag for allowing
in-kernel buffer copy, so that the PCM drivers can pass the buffer in
kernel-space later directly without set_fs() hackery.

The latest codes are found in topic/kill-set_fs branch of sound git
tree.

The media people are Cc'ed for solo6x10 changes.


Takashi

===

Takashi Iwai (16):
  ALSA: pcm: Introduce copy_silence PCM ops
  ALSA: Update document about copy_silence PCM ops
  ALSA: dummy: Convert to copy_silence ops
  ALSA: es1938: Convert to copy_silence ops
  ALSA: korg1212: Convert to copy_silence ops
  ALSA: nm256: Convert to copy_silence ops
  ALSA: rme32: Convert to copy_silence ops
  ALSA: rme96: Convert to copy_silence ops
  ALSA: rme9652: Convert to copy_silence ops
  ALSA: hdsp: Convert to copy_silence ops
  ALSA: gus: Convert to copy_silence ops
  ALSA: sb: Convert to copy_silence ops
  ALSA: sh: Convert to copy_silence ops
  ASoC: blackfin: Convert to copy_silence ops
  [media] solo6x10: Convert to copy_silence ops
  ALSA: pcm: Drop the old copy and silence ops

 .../sound/kernel-api/writing-an-alsa-driver.rst| 110 ++
 drivers/media/pci/solo6x10/solo6x10-g723.c |  13 ++-
 include/sound/pcm.h|   8 +-
 sound/core/pcm_lib.c   |  68 ++-
 sound/drivers/dummy.c  |  13 +--
 sound/isa/gus/gus_pcm.c|  43 ++-
 sound/isa/sb/emu8000_pcm.c |  99 +---
 sound/pci/es1938.c |  11 +-
 sound/pci/korg1212/korg1212.c  | 128 ++---
 sound/pci/nm256/nm256.c|  35 +++---
 sound/pci/rme32.c  |  49 
 sound/pci/rme96.c  |  52 -
 sound/pci/rme9652/hdsp.c   |  44 ---
 sound/pci/rme9652/rme9652.c|  46 
 sound/sh/sh_dac_audio.c|  40 ++-
 sound/soc/blackfin/bf5xx-ac97-pcm.c|   6 +-
 sound/soc/blackfin/bf5xx-ac97.c|  18 ++-
 sound/soc/blackfin/bf5xx-i2s-pcm.c |  46 +++-
 sound/soc/soc-pcm.c|   3 +-
 19 files changed, 340 insertions(+), 492 deletions(-)

-- 
2.13.0



Re: [PATCH v6 3/3] sound/usb: Use Media Controller API to share media resources

2016-12-06 Thread Takashi Iwai
On Tue, 06 Dec 2016 19:41:37 +0100,
Shuah Khan wrote:
> 
> Hi Takashi,
> 
> On 12/05/2016 11:50 PM, Takashi Iwai wrote:
> > On Wed, 30 Nov 2016 23:01:16 +0100,
> > Shuah Khan wrote:
> >>
> >> --- a/sound/usb/card.c
> >> +++ b/sound/usb/card.c
> > (snip)
> >> @@ -616,6 +617,11 @@ static int usb_audio_probe(struct usb_interface *intf,
> >>if (err < 0)
> >>goto __error;
> >>  
> >> +  if (quirk && quirk->media_device) {
> >> +  /* don't want to fail when media_snd_device_create() fails */
> >> +  media_snd_device_create(chip, intf);
> > 
> > Note that the usb-audio driver is probed for each usb interface, and
> > there are multiple interfaces per device.  That is, usb_audio_probe()
> > may be called multiple times per device, and at the second or the
> > later calls, it appends the stuff onto the previously created card
> > object.
> > 
> > So, you'd have to make this call also conditional (e.g. check
> > chip->num_interfaces == 0, indicating the very first one), or allow to
> > be called multiple times.
> > 
> > In the former case, it'd be better to split media_snd_device_create()
> > and media_snd_mixer_init().  The *_device_create() needs to be called
> > only once, while *_mixer_init() still has to be called for each time
> > because the new mixer element may be added for each interface.
> > 
> 
> Thanks for the catch. I am able to fix this in media_snd_device_create()
> I made a change to do media_dev allocate only once. media_snd_mixer_init()
> will get called every time media_snd_device_create() is called. This way
> new mixers can be handled. media_snd_mixer_init() has logic to deal with
> mixers that are already initialized. We are good here with the following
> change:
> 
> @@ -272,6 +258,14 @@ int media_snd_device_create(struct snd_usb_audio *chip,
> struct usb_device *usbdev = interface_to_usbdev(iface);
> int ret;
>  
> +   /* usb-audio driver is probed for each usb interface, and
> +* there are multiple interfaces per device. Avoid calling
> +* media_device_usb_allocate() each time usb_audio_probe()
> +* is called. Do it only once.
> +*/
> +   if (chip->media_dev)
> +   goto snd_mixer_init;
> +
> mdev = media_device_usb_allocate(usbdev, KBUILD_MODNAME);
> if (!mdev)
> return -ENOMEM;
> @@ -291,6 +285,7 @@ int media_snd_device_create(struct snd_usb_audio *chip,
> /* save media device - avoid lookups */
> chip->media_dev = mdev;
>  
> +snd_mixer_init:
> /* Create media entities for mixer and control dev */
> ret = media_snd_mixer_init(chip);
> if (ret) {

This looks good enough, yes.

> 
> > 
> >> +  }
> >> +
> >>usb_chip[chip->index] = chip;
> >>chip->num_interfaces++;
> >>usb_set_intfdata(intf, chip);
> >> @@ -672,6 +678,14 @@ static void usb_audio_disconnect(struct usb_interface 
> >> *intf)
> >>list_for_each(p, >midi_list) {
> >>snd_usbmidi_disconnect(p);
> >>}
> >> +  /*
> >> +   * Nice to check quirk && quirk->media_device and
> >> +   * then call media_snd_device_delete(). Don't have
> >> +   * access to quirk here. media_snd_device_delete()
> >> +   * acceses mixer_list
> >> +   */
> >> +  media_snd_device_delete(chip);
> > 
> > ... meanwhile this is OK, as it's called only once.
> > 
> > (BTW, is it OK to call media_* stuff while the device is still in use?
> >  The disconnect callback gets called for hot-unplug.)
> > 
> 
> Yes. All of the media_* functions that get called during run-time check for
> chip->media_dev or media_ctl and do nothing when these are null.
> 
> media_device itself will not be free'd until all reference are gone. When
> usb_audio_disconnect() happens via unbind snd_usb_audio or physical remove,
> media_dev sticks around until au0828 (media driver) goes away. There is
> handling for any user apps. that have /dev/mediaX open.
> 
> Does this sound correct? Did I miss any of your concerns?

That sounds all good, so it's safe to call there.


thanks,

Takashi
--
To unsubscribe from this list: send the line "unsubscribe linux-media" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH v6 3/3] sound/usb: Use Media Controller API to share media resources

2016-12-05 Thread Takashi Iwai
On Mon, 05 Dec 2016 23:44:30 +0100,
Shuah Khan wrote:
> 
> On 11/30/2016 03:01 PM, Shuah Khan wrote:
> > Change ALSA driver to use Media Controller API to share media resources
> > with DVB, and V4L2 drivers on a AU0828 media device.
> > 
> > Media Controller specific initialization is done after sound card is
> > registered. ALSA creates Media interface and entity function graph
> > nodes for Control, Mixer, PCM Playback, and PCM Capture devices.
> > 
> > snd_usb_hw_params() will call Media Controller enable source handler
> > interface to request the media resource. If resource request is granted,
> > it will release it from snd_usb_hw_free(). If resource is busy, -EBUSY is
> > returned.
> > 
> > Media specific cleanup is done in usb_audio_disconnect().
> > 
> > Signed-off-by: Shuah Khan 
> 
> Hi Takashi,
> 
> If you are good with this patch, could you please Ack it, so Mauro
> can pull it into media tree with the other two patches in this series,
> when he is ready to do so.

Sorry for the late review.

The biggest concern right now is the way the driver is probed.  As
mentioned in the review reply, we need to consider the cases where the
probe is called multiple times.  Other things are minor.


thanks,

Takashi
--
To unsubscribe from this list: send the line "unsubscribe linux-media" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH v6 3/3] sound/usb: Use Media Controller API to share media resources

2016-12-05 Thread Takashi Iwai
On Wed, 30 Nov 2016 23:01:16 +0100,
Shuah Khan wrote:
> 
> --- a/sound/usb/card.c
> +++ b/sound/usb/card.c
(snip)
> @@ -616,6 +617,11 @@ static int usb_audio_probe(struct usb_interface *intf,
>   if (err < 0)
>   goto __error;
>  
> + if (quirk && quirk->media_device) {
> + /* don't want to fail when media_snd_device_create() fails */
> + media_snd_device_create(chip, intf);

Note that the usb-audio driver is probed for each usb interface, and
there are multiple interfaces per device.  That is, usb_audio_probe()
may be called multiple times per device, and at the second or the
later calls, it appends the stuff onto the previously created card
object.

So, you'd have to make this call also conditional (e.g. check
chip->num_interfaces == 0, indicating the very first one), or allow to
be called multiple times.

In the former case, it'd be better to split media_snd_device_create()
and media_snd_mixer_init().  The *_device_create() needs to be called
only once, while *_mixer_init() still has to be called for each time
because the new mixer element may be added for each interface.


> + }
> +
>   usb_chip[chip->index] = chip;
>   chip->num_interfaces++;
>   usb_set_intfdata(intf, chip);
> @@ -672,6 +678,14 @@ static void usb_audio_disconnect(struct usb_interface 
> *intf)
>   list_for_each(p, >midi_list) {
>   snd_usbmidi_disconnect(p);
>   }
> + /*
> +  * Nice to check quirk && quirk->media_device and
> +  * then call media_snd_device_delete(). Don't have
> +  * access to quirk here. media_snd_device_delete()
> +  * acceses mixer_list
> +  */
> + media_snd_device_delete(chip);

... meanwhile this is OK, as it's called only once.

(BTW, is it OK to call media_* stuff while the device is still in use?
 The disconnect callback gets called for hot-unplug.)


> --- /dev/null
> +++ b/sound/usb/media.c
(snip)
> +void media_snd_stream_delete(struct snd_usb_substream *subs)
> +{
> + struct media_ctl *mctl = subs->media_ctl;
> +
> + if (mctl && mctl->media_dev) {

mctl->media_dev NULL check here is superfluous, as it's checked
mctl->below.

> + struct media_device *mdev;
> +
> + mdev = mctl->media_dev;
> + if (mdev && media_devnode_is_registered(mdev->devnode)) {
> + media_devnode_remove(mctl->intf_devnode);
> + media_device_unregister_entity(>media_entity);
> + media_entity_cleanup(>media_entity);
> + }
> + kfree(mctl);
> + subs->media_ctl = NULL;
> + }
> +}
> +
> +int media_snd_start_pipeline(struct snd_usb_substream *subs)
> +{
> + struct media_ctl *mctl = subs->media_ctl;
> +
> + if (mctl)
> + return media_snd_enable_source(mctl);
> + return 0;
> +}

It's merely a wrapper, and media_snd_enable_source() itself checks
NULL mctl.  So we can replace media_snd_enable_source() with
media_snd_start_pipeline().

> +void media_snd_stop_pipeline(struct snd_usb_substream *subs)
> +{
> + struct media_ctl *mctl = subs->media_ctl;
> +
> + if (mctl)
> + media_snd_disable_source(mctl);
> +}

Ditto.

> diff --git a/sound/usb/pcm.c b/sound/usb/pcm.c
> index 44d178e..0e4e0640 100644
> --- a/sound/usb/pcm.c
> +++ b/sound/usb/pcm.c
(snip)
> @@ -717,10 +718,14 @@ static int snd_usb_hw_params(struct snd_pcm_substream 
> *substream,
>   struct audioformat *fmt;
>   int ret;
>  
> + ret = media_snd_start_pipeline(subs);
> + if (ret)
> + return ret;

It's an open question at which timing we should call
media_snd_start_pipeline().  The hw_params is mostly OK, while the
real timing where the stream might be started is the prepare
callback.  I guess we can keep as is for now.

Also, one more thing to be considered is whether
media_snd_start_pipeline() can be called multiple times.  hw_params
and prepare callbacks may be called multiple times.  I suppose it's
OK, but just to be sure.


> @@ -1234,7 +1246,12 @@ static int snd_usb_pcm_open(struct snd_pcm_substream 
> *substream, int direction)
>   subs->dsd_dop.channel = 0;
>   subs->dsd_dop.marker = 1;
>  
> - return setup_hw_info(runtime, subs);
> + ret = setup_hw_info(runtime, subs);
> + if (ret == 0)
> + ret = media_snd_stream_init(subs, as->pcm, direction);
> + if (ret)
> + snd_usb_autosuspend(subs->stream->chip);
> + return ret;

This leads to the PM refcount unbalance.  The call of
snd_usb_autosuspend() must be in the former if block,

ret = setup_hw_info(runtime, subs);
if (ret == 0) {
ret = media_snd_stream_init(subs, as->pcm, direction);
if (ret)
snd_usb_autosuspend(subs->stream->chip);
}
return ret;


thanks,

Takashi
--
To unsubscribe from this list: 

Re: [RFC][PATCH 0/2] ALSA: control: export all of TLV related macros to user land

2016-09-11 Thread Takashi Iwai
On Sun, 11 Sep 2016 05:06:41 +0200,
Takashi Sakamoto wrote:
> 
> On Sep 10 2016 22:41, Takashi Iwai wrote:
> > On Sat, 10 Sep 2016 09:25:31 +0200,
> > Takashi Sakamoto wrote:
> >>
> >> On Sep 10 2016 15:44, Takashi Iwai wrote:
> >>> On Sat, 10 Sep 2016 06:50:14 +0200,
> >>> Takashi Sakamoto wrote:
> >>>>
> >>>> Hi,
> >>>>
> >>>> Currently, TLV related protocol is not shared to user land. This is not
> >>>> good in a point of application interfaces, because application developers
> >>>> can't realize the protocol just to see UAPI headers.
> >>>>
> >>>> For this purpose, this patchset moves all of macros related to TLV to 
> >>>> UAPI
> >>>> header. As a result, a header just for kernel land is obsoleted. When 
> >>>> adding
> >>>> new items to the protocol, it's added to the UAPI header. This change 
> >>>> affects
> >>>> some drivers in media subsystem.
> >>>>
> >>>> In my concern, this change can break applications. When these macros are
> >>>> already defined in application side and they includes tlv UAPI header
> >>>> directly, 'redefined' warning is generated at preprocess time. But the
> >>>> compilation will be success itself. If these two macros have different
> >>>> content, the result of preprocess is dominated to the order to define.
> >>>> However, the most applications are assumed to use TLV feature via 
> >>>> libraries
> >>>> such as alsa-lib, thus I'm optimistic to this concern.
> >>>>
> >>>> As another my concern, the name of these macros are quite simple, as
> >>>> 'TLV_XXX'. It might be help application developers to rename them with a
> >>>> prefix, as 'SNDRV_CTL_TLV_XXX'. (But not yet. I'm a lazy guy.)
> >>>
> >>> The second patch does simply wrong.  You must not obsolete
> >>> include/sound/tlv.h.  Even if it includes only uapi/*, it should be
> >>> still there.
> >>
> >> Any reasons?
> > 
> > The concept and the design.
> > 
> > Don't need to change the root inclusion, it's just to provide cleaner
> > uapi header files, and not meant to be included directly -- it was the
> > basic idea when uapi split was introduced.
> 
> OK. I can see what you indicated in this post for UAPI idea[0]. I'm
> ready to drop the second patch.
> 
> Well, how do you think about my concern of macro prefix? For example, we
> can apply below step:
> 
> Put substantial macros with renaming to 'include/uapi.sound/tlv.h':
> #define SNDRV_CTL_TLV_DATA_LENGTH(...) \
>((unsigned int)sizeof((const unsigned int[]) { __VA_ARGS__ }))
> 
> Then, put alias macros to 'include/sound/tlv.h':
> #include 
> #define TLV_LENGTH SNDRV_CTL_TLV_DATA_LENGTH
> ...
> 
> Finally, applications can expand these macro with apparent names with
> prefix of 'SNDRV_CTL_TLV_DATA_XXX'. I think the prefix prevent
> application codes from name conflict by including 'uapi/sound/tlv.h'.

Yes, that would work.


Takashi
--
To unsubscribe from this list: send the line "unsubscribe linux-media" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [RFC][PATCH 0/2] ALSA: control: export all of TLV related macros to user land

2016-09-10 Thread Takashi Iwai
On Sat, 10 Sep 2016 09:25:31 +0200,
Takashi Sakamoto wrote:
> 
> On Sep 10 2016 15:44, Takashi Iwai wrote:
> > On Sat, 10 Sep 2016 06:50:14 +0200,
> > Takashi Sakamoto wrote:
> >>
> >> Hi,
> >>
> >> Currently, TLV related protocol is not shared to user land. This is not
> >> good in a point of application interfaces, because application developers
> >> can't realize the protocol just to see UAPI headers.
> >>
> >> For this purpose, this patchset moves all of macros related to TLV to UAPI
> >> header. As a result, a header just for kernel land is obsoleted. When 
> >> adding
> >> new items to the protocol, it's added to the UAPI header. This change 
> >> affects
> >> some drivers in media subsystem.
> >>
> >> In my concern, this change can break applications. When these macros are
> >> already defined in application side and they includes tlv UAPI header
> >> directly, 'redefined' warning is generated at preprocess time. But the
> >> compilation will be success itself. If these two macros have different
> >> content, the result of preprocess is dominated to the order to define.
> >> However, the most applications are assumed to use TLV feature via libraries
> >> such as alsa-lib, thus I'm optimistic to this concern.
> >>
> >> As another my concern, the name of these macros are quite simple, as
> >> 'TLV_XXX'. It might be help application developers to rename them with a
> >> prefix, as 'SNDRV_CTL_TLV_XXX'. (But not yet. I'm a lazy guy.)
> > 
> > The second patch does simply wrong.  You must not obsolete
> > include/sound/tlv.h.  Even if it includes only uapi/*, it should be
> > still there.
> 
> Any reasons?

The concept and the design.

Don't need to change the root inclusion, it's just to provide cleaner
uapi header files, and not meant to be included directly -- it was the
basic idea when uapi split was introduced.


Takashi
--
To unsubscribe from this list: send the line "unsubscribe linux-media" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [RFC][PATCH 0/2] ALSA: control: export all of TLV related macros to user land

2016-09-10 Thread Takashi Iwai
On Sat, 10 Sep 2016 06:50:14 +0200,
Takashi Sakamoto wrote:
> 
> Hi,
> 
> Currently, TLV related protocol is not shared to user land. This is not
> good in a point of application interfaces, because application developers
> can't realize the protocol just to see UAPI headers.
> 
> For this purpose, this patchset moves all of macros related to TLV to UAPI
> header. As a result, a header just for kernel land is obsoleted. When adding
> new items to the protocol, it's added to the UAPI header. This change affects
> some drivers in media subsystem.
> 
> In my concern, this change can break applications. When these macros are
> already defined in application side and they includes tlv UAPI header
> directly, 'redefined' warning is generated at preprocess time. But the
> compilation will be success itself. If these two macros have different
> content, the result of preprocess is dominated to the order to define.
> However, the most applications are assumed to use TLV feature via libraries
> such as alsa-lib, thus I'm optimistic to this concern.
> 
> As another my concern, the name of these macros are quite simple, as
> 'TLV_XXX'. It might be help application developers to rename them with a
> prefix, as 'SNDRV_CTL_TLV_XXX'. (But not yet. I'm a lazy guy.)

The second patch does simply wrong.  You must not obsolete
include/sound/tlv.h.  Even if it includes only uapi/*, it should be
still there.

So, just move the stuff to include/uapi/sound/tlv.h, and that's all.


thanks,

Takashi
--
To unsubscribe from this list: send the line "unsubscribe linux-media" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [alsa-devel] [very-RFC 0/8] TSN driver for the kernel

2016-06-21 Thread Takashi Iwai
On Tue, 21 Jun 2016 08:38:57 +0200,
Richard Cochran wrote:
> 
> On Tue, Jun 21, 2016 at 07:54:32AM +0200, Takashi Iwai wrote:
> > > I still would appreciate an answer to my other questions, though...
> > 
> > Currently HD-audio (both ASoC and legacy ones) are the only drivers
> > providing the link timestamp.  In the recent code, it's PCM
> > get_time_info ops, so you can easily grep it.
> 
> Yes, I found that myself, thanks.
>  
> > HTH,
> 
> No it doesn't help me, because I asked three questions, and none were
> about the link timestamp.

??  The extended audio timpestamp is essentially to return the link
timestamp.  Just the term has changed along time...


Takashi
--
To unsubscribe from this list: send the line "unsubscribe linux-media" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [alsa-devel] [very-RFC 0/8] TSN driver for the kernel

2016-06-20 Thread Takashi Iwai
On Mon, 20 Jun 2016 17:21:26 +0200,
Richard Cochran wrote:
> 
> On Mon, Jun 20, 2016 at 02:31:48PM +0200, Richard Cochran wrote:
> > Where is this "audio_time" program of which you speak?
> 
> Never mind, found it in alsa-lib.
> 
> I still would appreciate an answer to my other questions, though...

Currently HD-audio (both ASoC and legacy ones) are the only drivers
providing the link timestamp.  In the recent code, it's PCM
get_time_info ops, so you can easily grep it.


HTH,

Takashi
--
To unsubscribe from this list: send the line "unsubscribe linux-media" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [RFC PATCH v2 0/5] Media Device Allocator API

2016-04-05 Thread Takashi Iwai
On Tue, 05 Apr 2016 05:35:55 +0200,
Shuah Khan wrote:
> 
> There are known problems with media device life time management. When media
> device is released while an media ioctl is in progress, ioctls fail with
> use-after-free errors and kernel hangs in some cases.
> 
> Media Device can be in any the following states:
> 
> - Allocated
> - Registered (could be tied to more than one driver)
> - Unregistered, not in use (media device file is not open)
> - Unregistered, in use (media device file is not open)
> - Released
> 
> When media device belongs to  more than one driver, registrations should be
> tracked to avoid unregistering when one of the drivers does unregister. A new
> num_drivers field in the struct media_device covers this case. The media 
> device
> should be unregistered only when the last unregister occurs with num_drivers
> count zero.
> 
> When a media device is in use when it is unregistered, it should not be
> released until the application exits when it detects the unregistered
> status. Media device that is in use when it is unregistered is moved to
> to_delete_list. When the last unregister occurs, media device is unregistered
> and becomes an unregistered, still allocated device. Unregister marks the
> device to be deleted.
> 
> When media device belongs to more than one driver, as both drivers could be
> unbound/bound, driver should not end up getting stale media device that is
> on its way out. Moving the unregistered media device to to_delete_list helps
> this case as well.
> 
> I ran bind/unbind loop tests on uvcvideo, au0828, and snd-usb-audio while
> running application that does ioctls. Didn't see any use-after-free errors
> on media device. A couple of known issues seen:
> 
> 1. When application exits, cdev_put() gets called after media device is
>released. This is a known issue to resolve and Media Device Allocator
>can't solve this one.
> 2. When au0828 module is removed and then ioctls fail when cdev_get() looks
>for the owning module as au0828 is very often the module that owns the
>media devnode. This is a cdev related issue that needs to be resolved and
>Media Device Allocator can't solve this one.
> 
> Shuah Khan (5):
>   media: Add Media Device Allocator API
>   media: Add driver count to keep track of media device registrations
>   media: uvcvideo change to use Media Device Allocator API
>   media: au0828 change to use Media Device Allocator API
>   sound/usb: Use Media Controller API to share media resources

I don't think we need to include usb-audio patch at this stage yet.
The most important thing for now is to improve / stabilize the API
itself so that other drivers can use it as is.  Once when the API is
really stabilized, we create a solid git branch that may be based for
multiple subsystems, and I'll merge usb-audio stuff through sound git
tree.

Also, the previous usb-audio MC implementation had a few serious bugs,
including quirk NULL dereference.  See the bugzilla below for some fix
patches to 4.6-rc1:
  https://bugzilla.kernel.org/show_bug.cgi?id=115561
Feel free to fold them in, if they are still valid.


thanks,

Takashi
--
To unsubscribe from this list: send the line "unsubscribe linux-media" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [alsa-devel] [PATCH] sound/usb: Fix memory leak in media_snd_stream_delete() during unbind

2016-03-19 Thread Takashi Iwai
On Thu, 17 Mar 2016 03:58:06 +0100,
Shuah Khan wrote:
> 
> media_snd_stream_delete() fails to release resources during unbind. This
> leads to use-after-free in media_gobj_create() on a subsequent bind.
> 
> [ 1445.086410] BUG: KASAN: use-after-free in media_gobj_create+0x3a1/0x470 
> [media] at addr 8801ead49998
> 
> [ 1445.086771] Call Trace:
> [ 1445.086779]  [] dump_stack+0x67/0x94
> [ 1445.086785]  [] print_trailer+0xf9/0x150
> [ 1445.086790]  [] object_err+0x34/0x40
> [ 1445.086796]  [] kasan_report_error+0x221/0x530
> [ 1445.086803]  [] __asan_report_store8_noabort+0x43/0x50
> [ 1445.086813]  [] ? media_gobj_create+0x3a1/0x470 [media]
> [ 1445.086822]  [] media_gobj_create+0x3a1/0x470 [media]
> [ 1445.086831]  [] media_device_register_entity+0x259/0x6f0 
> [media]
> [ 1445.086841]  [] ? 
> media_device_unregister_entity_notify+0x100/0x100 [media]
> [ 1445.086846]  [] ? ___slab_alloc+0x172/0x500
> [ 1445.086854]  [] ? mark_held_locks+0xc8/0x120
> [ 1445.086859]  [] ? __slab_alloc+0x50/0x70
> [ 1445.086878]  [] ? media_snd_mixer_init+0x16c/0x500 
> [snd_usb_audio]
> [ 1445.086884]  [] ? kasan_unpoison_shadow+0x36/0x50
> [ 1445.086890]  [] ? kasan_unpoison_shadow+0x36/0x50
> [ 1445.086895]  [] ? kasan_kmalloc+0x5e/0x70
> 
> Signed-off-by: Shuah Khan <shua...@osg.samsung.com>

Mauro, please take it through your tree.

Acked-by: Takashi Iwai <ti...@suse.de>


thanks,

Takashi

> ---
>  sound/usb/media.c | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)
> 
> diff --git a/sound/usb/media.c b/sound/usb/media.c
> index 44a5de9..0d03773 100644
> --- a/sound/usb/media.c
> +++ b/sound/usb/media.c
> @@ -135,7 +135,7 @@ void media_snd_stream_delete(struct snd_usb_substream 
> *subs)
>   if (mctl && mctl->media_dev) {
>   struct media_device *mdev;
>  
> - mdev = subs->stream->chip->media_dev;
> + mdev = mctl->media_dev;
>   if (mdev && media_devnode_is_registered(>devnode)) {
>   media_devnode_remove(mctl->intf_devnode);
>   media_device_unregister_entity(>media_entity);
> -- 
> 2.5.0
> 
> ___
> Alsa-devel mailing list
> alsa-de...@alsa-project.org
> http://mailman.alsa-project.org/mailman/listinfo/alsa-devel
> 
--
To unsubscribe from this list: send the line "unsubscribe linux-media" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH] media: add GFP flag to media_*() that could get called in atomic context

2016-03-14 Thread Takashi Iwai
On Mon, 14 Mar 2016 11:13:58 +0100,
Mauro Carvalho Chehab wrote:
> 
> Em Mon, 14 Mar 2016 09:22:37 +0200
> Sakari Ailus  escreveu:
> 
> > Hi Shuah,
> > 
> > On Sat, Mar 12, 2016 at 06:48:09PM -0700, Shuah Khan wrote:
> > > Add GFP flags to media_create_pad_link(), media_create_intf_link(),
> > > media_devnode_create(), and media_add_link() that could get called
> > > in atomic context to allow callers to pass in the right flags for
> > > memory allocation.
> > > 
> > > tree-wide driver changes for media_*() GFP flags change:
> > > Change drivers to add gfpflags to interffaces, media_create_pad_link(),
> > > media_create_intf_link() and media_devnode_create().
> > > 
> > > Signed-off-by: Shuah Khan 
> > > Suggested-by: Mauro Carvalho Chehab   
> > 
> > What's the use case for calling the above functions in an atomic context?
> > 
> 
> ALSA code seems to do a lot of stuff at atomic context. That's what
> happens on my test machine when au0828 gets probed before
> snd-usb-audio:
>   http://pastebin.com/LEX5LD5K
> 
> It seems that ALSA USB probe routine (usb_audio_probe) happens in
> atomic context.

No, usb_audio_probe() doesn't take a lock.  But
media_device_register_entity() seems taking a spinlock, instead.


Takashi
--
To unsubscribe from this list: send the line "unsubscribe linux-media" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH 26/31] sound/usb: Update ALSA driver to use Managed Media Controller API

2016-01-07 Thread Takashi Iwai
On Wed, 06 Jan 2016 22:05:35 +0100,
Shuah Khan wrote:
> 
> diff --git a/sound/usb/Makefile b/sound/usb/Makefile
> index 2d2d122..665fdd9 100644
> --- a/sound/usb/Makefile
> +++ b/sound/usb/Makefile
> @@ -2,6 +2,18 @@
>  # Makefile for ALSA
>  #
>  
> +# Media Controller
> +ifeq ($(CONFIG_MEDIA_CONTROLLER),y)
> +  ifeq ($(CONFIG_MEDIA_SUPPORT),y)
> +KBUILD_CFLAGS += -DUSE_MEDIA_CONTROLLER
> +  endif
> +  ifeq ($(CONFIG_MEDIA_SUPPORT_MODULE),y)
> +ifeq ($(MODULE),y)
> +  KBUILD_CFLAGS += -DUSE_MEDIA_CONTROLLER
> +endif
> +  endif
> +endif

Can't we define this rather via Kconfig?
Doing this in Makefile is way too tricky, and it's unclear to users
whether MC is actually enabled or not.


> diff --git a/sound/usb/media.c b/sound/usb/media.c
> new file mode 100644
> index 000..747a66a
> --- /dev/null
> +++ b/sound/usb/media.c
> @@ -0,0 +1,214 @@
> +/*
> + * media.c - Media Controller specific ALSA driver code
> + *
> + * Copyright (c) 2015 Shuah Khan 
> + * Copyright (c) 2015 Samsung Electronics Co., Ltd.
> + *
> + * This file is released under the GPLv2.
> + */
> +
> +/*
> + * This file adds Media Controller support to ALSA driver
> + * to use the Media Controller API to share tuner with DVB
> + * and V4L2 drivers that control media device. Media device
> + * is created based on existing quirks framework. Using this
> + * approach, the media controller API usage can be added for
> + * a specific device.
> +*/
> +
> +#include 
> +#include 
> +#include 
> +#include 
> +#include 
> +#include 
> +#include 
> +#include 
> +#include 
> +#include 
> +#include 
> +
> +#include 
> +#include 
> +#include 
> +#include 
> +#include 
> +#include 
> +
> +#include "usbaudio.h"
> +#include "card.h"
> +#include "midi.h"
> +#include "mixer.h"
> +#include "proc.h"
> +#include "quirks.h"
> +#include "endpoint.h"
> +#include "helper.h"
> +#include "debug.h"
> +#include "pcm.h"
> +#include "format.h"
> +#include "power.h"
> +#include "stream.h"
> +#include "media.h"

I believe we can get rid of many include files just for MC support...


> +#ifdef USE_MEDIA_CONTROLLER

This ifdef can be removed once if we build this object file
conditionally in Makefile.


> @@ -1232,7 +1244,10 @@ static int snd_usb_pcm_open(struct snd_pcm_substream 
> *substream, int direction)
>   subs->dsd_dop.channel = 0;
>   subs->dsd_dop.marker = 1;
>  
> - return setup_hw_info(runtime, subs);
> + ret = setup_hw_info(runtime, subs);
> + if (ret == 0)
> + ret = media_stream_init(subs, as->pcm, direction);

Need to call snd_usb_autosuspend() in the error path.


> --- a/sound/usb/quirks.c
> +++ b/sound/usb/quirks.c
> @@ -544,13 +545,19 @@ int snd_usb_create_quirk(struct snd_usb_audio *chip,
>   [QUIRK_AUDIO_ALIGN_TRANSFER] = create_align_transfer_quirk,
>   [QUIRK_AUDIO_STANDARD_MIXER] = create_standard_mixer_quirk,
>   };
> + int ret;
>  
> + if (quirk->media_device) {
> + /* don't want to fail when media_device_create() fails */
> + media_device_create(chip, iface);
> + }

So far, so good...

>   if (quirk->type < QUIRK_TYPE_COUNT) {
> - return quirk_funcs[quirk->type](chip, iface, driver, quirk);
> + ret = quirk_funcs[quirk->type](chip, iface, driver, quirk);
>   } else {
>   usb_audio_err(chip, "invalid quirk type %d\n", quirk->type);
>   return -ENXIO;
>   }
> + return ret;

Any reason to change this?


Takashi
--
To unsubscribe from this list: send the line "unsubscribe linux-media" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [alsa-devel] [PATCH MC Next Gen] sound/usb: Fix out of bounds access in media_entity_init()

2015-12-07 Thread Takashi Iwai
On Sat, 05 Dec 2015 01:00:29 +0100,
Shuah Khan wrote:
> 
> Fix the out of bounds access in media_entity_init() found
> by KASan. This is a result of media_mixer_init() failing
> to allocate memory for all 3 of its pads before calling
> media_entity_init(). Fix it to allocate memory for the
> right struct media_mixer_ctl instead of struct media_ctl.
> 
> Signed-off-by: Shuah Khan 
> ---
> 
> This patch fixes the mixer patch below:
> https://patchwork.linuxtv.org/patch/31827/
> 
>  sound/usb/media.c | 5 +++--
>  1 file changed, 3 insertions(+), 2 deletions(-)
> 
> diff --git a/sound/usb/media.c b/sound/usb/media.c
> index bebe27b..0cb44b9 100644
> --- a/sound/usb/media.c
> +++ b/sound/usb/media.c
> @@ -233,8 +233,8 @@ int media_mixer_init(struct snd_usb_audio *chip)
>   if (mixer->media_mixer_ctl)
>   continue;
>  
> - /* allocate media_ctl */
> - mctl = kzalloc(sizeof(struct media_ctl), GFP_KERNEL);
> + /* allocate media_mixer_ctl */
> + mctl = kzalloc(sizeof(struct media_mixer_ctl), GFP_KERNEL);

Isn't it better to use sizeof(*mctl)?


Takashi
--
To unsubscribe from this list: send the line "unsubscribe linux-media" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH] media, sound: tea575x: constify snd_tea575x_ops structures

2015-11-22 Thread Takashi Iwai
On Sun, 22 Nov 2015 11:32:53 +0100,
Julia Lawall wrote:
> 
> The snd_tea575x_ops structures are never modified, so declare them as
> const.
> 
> Done with the help of Coccinelle.
> 
> Signed-off-by: Julia Lawall <julia.law...@lip6.fr>

Reviewed-by: Takashi Iwai <ti...@suse.de>

Feel free to take via media tree.


thanks,

Takashi

> 
> ---
>  drivers/media/pci/bt8xx/bttv-cards.c  |2 +-
>  drivers/media/radio/radio-maxiradio.c |2 +-
>  drivers/media/radio/radio-sf16fmr2.c  |2 +-
>  drivers/media/radio/radio-shark.c |2 +-
>  include/media/drv-intf/tea575x.h  |2 +-
>  sound/pci/es1968.c|2 +-
>  sound/pci/fm801.c |2 +-
>  7 files changed, 7 insertions(+), 7 deletions(-)
> 
> diff --git a/sound/pci/es1968.c b/sound/pci/es1968.c
> index cb38cd1..514f260 100644
> --- a/sound/pci/es1968.c
> +++ b/sound/pci/es1968.c
> @@ -2605,7 +2605,7 @@ static void snd_es1968_tea575x_set_direction(struct 
> snd_tea575x *tea, bool outpu
>   }
>  }
>  
> -static struct snd_tea575x_ops snd_es1968_tea_ops = {
> +static const struct snd_tea575x_ops snd_es1968_tea_ops = {
>   .set_pins = snd_es1968_tea575x_set_pins,
>   .get_pins = snd_es1968_tea575x_get_pins,
>   .set_direction = snd_es1968_tea575x_set_direction,
> diff --git a/sound/pci/fm801.c b/sound/pci/fm801.c
> index 5144a7f..759295a 100644
> --- a/sound/pci/fm801.c
> +++ b/sound/pci/fm801.c
> @@ -815,7 +815,7 @@ static void snd_fm801_tea575x_set_direction(struct 
> snd_tea575x *tea, bool output
>   fm801_writew(chip, GPIO_CTRL, reg);
>  }
>  
> -static struct snd_tea575x_ops snd_fm801_tea_ops = {
> +static const struct snd_tea575x_ops snd_fm801_tea_ops = {
>   .set_pins = snd_fm801_tea575x_set_pins,
>   .get_pins = snd_fm801_tea575x_get_pins,
>   .set_direction = snd_fm801_tea575x_set_direction,
> diff --git a/drivers/media/pci/bt8xx/bttv-cards.c 
> b/drivers/media/pci/bt8xx/bttv-cards.c
> index 7a08102..8a17cc0 100644
> --- a/drivers/media/pci/bt8xx/bttv-cards.c
> +++ b/drivers/media/pci/bt8xx/bttv-cards.c
> @@ -3808,7 +3808,7 @@ static void bttv_tea575x_set_direction(struct 
> snd_tea575x *tea, bool output)
>   gpio_inout(mask, (1 << gpio.clk) | (1 << gpio.wren));
>  }
>  
> -static struct snd_tea575x_ops bttv_tea_ops = {
> +static const struct snd_tea575x_ops bttv_tea_ops = {
>   .set_pins = bttv_tea575x_set_pins,
>   .get_pins = bttv_tea575x_get_pins,
>   .set_direction = bttv_tea575x_set_direction,
> diff --git a/drivers/media/radio/radio-sf16fmr2.c 
> b/drivers/media/radio/radio-sf16fmr2.c
> index 8e4f1d1..dc81d42 100644
> --- a/drivers/media/radio/radio-sf16fmr2.c
> +++ b/drivers/media/radio/radio-sf16fmr2.c
> @@ -82,7 +82,7 @@ static void fmr2_tea575x_set_direction(struct snd_tea575x 
> *tea, bool output)
>  {
>  }
>  
> -static struct snd_tea575x_ops fmr2_tea_ops = {
> +static const struct snd_tea575x_ops fmr2_tea_ops = {
>   .set_pins = fmr2_tea575x_set_pins,
>   .get_pins = fmr2_tea575x_get_pins,
>   .set_direction = fmr2_tea575x_set_direction,
> diff --git a/include/media/drv-intf/tea575x.h 
> b/include/media/drv-intf/tea575x.h
> index 5d09657..fb272d4 100644
> --- a/include/media/drv-intf/tea575x.h
> +++ b/include/media/drv-intf/tea575x.h
> @@ -63,7 +63,7 @@ struct snd_tea575x {
>   u32 band;   /* 0: FM, 1: FM-Japan, 2: AM */
>   u32 freq;   /* frequency */
>   struct mutex mutex;
> - struct snd_tea575x_ops *ops;
> + const struct snd_tea575x_ops *ops;
>   void *private_data;
>   u8 card[32];
>   u8 bus_info[32];
> diff --git a/drivers/media/radio/radio-shark.c 
> b/drivers/media/radio/radio-shark.c
> index 409fac1..85667a9 100644
> --- a/drivers/media/radio/radio-shark.c
> +++ b/drivers/media/radio/radio-shark.c
> @@ -150,7 +150,7 @@ static u32 shark_read_val(struct snd_tea575x *tea)
>   return val;
>  }
>  
> -static struct snd_tea575x_ops shark_tea_ops = {
> +static const struct snd_tea575x_ops shark_tea_ops = {
>   .write_val = shark_write_val,
>   .read_val  = shark_read_val,
>  };
> diff --git a/drivers/media/radio/radio-maxiradio.c 
> b/drivers/media/radio/radio-maxiradio.c
> index 41c1652..70fd8e8 100644
> --- a/drivers/media/radio/radio-maxiradio.c
> +++ b/drivers/media/radio/radio-maxiradio.c
> @@ -108,7 +108,7 @@ static void maxiradio_tea575x_set_direction(struct 
> snd_tea575x *tea, bool output
>  {
>  }
>  
> -static struct snd_tea575x_ops maxiradio_tea_ops = {
> +static const struct snd_tea575x_ops maxiradio_tea_ops = {
>   .set_pins = maxiradio_tea575x_set_pins,
>   .get_pins = maxiradio_tea575x_get_pins,
>   .set_direction = maxiradio_tea575x_set_direction,
> 
> 
--
To unsubscribe from this list: send the line "unsubscribe linux-media" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH MC Next Gen v2 2/3] sound/usb: Create media mixer function and control interface entities

2015-11-03 Thread Takashi Iwai
On Tue, 03 Nov 2015 17:06:45 +0100,
Shuah Khan wrote:
> 
> On 10/25/2015 03:37 PM, Shuah Khan wrote:
> > On 10/22/2015 01:16 AM, Takashi Iwai wrote:
> >> On Wed, 21 Oct 2015 01:25:15 +0200,
> >> Shuah Khan wrote:
> >>>
> >>> Add support for creating MEDIA_ENT_F_AUDIO_MIXER entity for
> >>> each mixer and a MEDIA_INTF_T_ALSA_CONTROL control interface
> >>> entity that links to mixer entities. MEDIA_INTF_T_ALSA_CONTROL
> >>> entity corresponds to the control device for the card.
> >>>
> >>> Signed-off-by: Shuah Khan <shua...@osg.samsung.com>
> >>> ---
> >>>   sound/usb/card.c |  5 +++
> >>>   sound/usb/media.c| 89
> >>> 
> >>>   sound/usb/media.h| 20 
> >>>   sound/usb/mixer.h|  1 +
> >>>   sound/usb/usbaudio.h |  1 +
> >>>   5 files changed, 116 insertions(+)
> >>>
> >>> diff --git a/sound/usb/card.c b/sound/usb/card.c
> >>> index 469d2bf..d004cb4 100644
> >>> --- a/sound/usb/card.c
> >>> +++ b/sound/usb/card.c
> >>> @@ -560,6 +560,9 @@ static int usb_audio_probe(struct usb_interface
> >>> *intf,
> >>>   if (err < 0)
> >>>   goto __error;
> >>>
> >>> +/* Create media entities for mixer and control dev */
> >>> +media_mixer_init(chip);
> >>> +
> >>>   usb_chip[chip->index] = chip;
> >>>   chip->num_interfaces++;
> >>>   chip->probing = 0;
> >>> @@ -616,6 +619,8 @@ static void usb_audio_disconnect(struct
> >>> usb_interface *intf)
> >>>   list_for_each(p, >midi_list) {
> >>>   snd_usbmidi_disconnect(p);
> >>>   }
> >>> +/* delete mixer media resources */
> >>> +media_mixer_delete(chip);
> >>>   /* release mixer resources */
> >>>   list_for_each_entry(mixer, >mixer_list, list) {
> >>>   snd_usb_mixer_disconnect(mixer);
> >>> diff --git a/sound/usb/media.c b/sound/usb/media.c
> >>> index 0cbfee6..a26ea8b 100644
> >>> --- a/sound/usb/media.c
> >>> +++ b/sound/usb/media.c
> >>> @@ -199,4 +199,93 @@ void media_stop_pipeline(struct
> >>> snd_usb_substream *subs)
> >>>   if (mctl)
> >>>   media_disable_source(mctl);
> >>>   }
> >>> +
> >>> +int media_mixer_init(struct snd_usb_audio *chip)
> >>> +{
> >>> +struct device *ctl_dev = >card->ctl_dev;
> >>> +struct media_intf_devnode *ctl_intf;
> >>> +struct usb_mixer_interface *mixer;
> >>> +struct media_device *mdev;
> >>> +struct media_mixer_ctl *mctl;
> >>> +u32 intf_type = MEDIA_INTF_T_ALSA_CONTROL;
> >>> +int ret;
> >>> +
> >>> +mdev = media_device_find_devres(>dev->dev);
> >>> +if (!mdev)
> >>> +return -ENODEV;
> >>> +
> >>> +ctl_intf = (struct media_intf_devnode *)
> >>> chip->ctl_intf_media_devnode;
> >>
> >> Why do we need cast?  Can't chip->ctl_intf_media_devnode itself be
> >> struct media_intf_devndoe pointer?
> > 
> > Yeah. There is no need to cast here. I will fix it.
> 
> Sorry I misspoke. The reason for this cast is ctl_intf_media_devnode
> is void to avoid including media.h and other media files in usbaudio.h

You can declare the struct without definition in each header file.
So just declare it and use it in usbaudio.h like:

struct media_intf_devnode;

struct snd_usb_audio {

struct media_intf_devnode *ctl_intf_media_devnode;


And even if you're using a void pointer there instead of the explicit
struct pointer, the cast is superfluous.  The implicit cast between a
void pointer and any other pointer is valid in plain C.


Takashi
--
To unsubscribe from this list: send the line "unsubscribe linux-media" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH MC Next Gen v2 2/3] sound/usb: Create media mixer function and control interface entities

2015-10-22 Thread Takashi Iwai
On Wed, 21 Oct 2015 01:25:15 +0200,
Shuah Khan wrote:
> 
> Add support for creating MEDIA_ENT_F_AUDIO_MIXER entity for
> each mixer and a MEDIA_INTF_T_ALSA_CONTROL control interface
> entity that links to mixer entities. MEDIA_INTF_T_ALSA_CONTROL
> entity corresponds to the control device for the card.
> 
> Signed-off-by: Shuah Khan 
> ---
>  sound/usb/card.c |  5 +++
>  sound/usb/media.c| 89 
> 
>  sound/usb/media.h| 20 
>  sound/usb/mixer.h|  1 +
>  sound/usb/usbaudio.h |  1 +
>  5 files changed, 116 insertions(+)
> 
> diff --git a/sound/usb/card.c b/sound/usb/card.c
> index 469d2bf..d004cb4 100644
> --- a/sound/usb/card.c
> +++ b/sound/usb/card.c
> @@ -560,6 +560,9 @@ static int usb_audio_probe(struct usb_interface *intf,
>   if (err < 0)
>   goto __error;
>  
> + /* Create media entities for mixer and control dev */
> + media_mixer_init(chip);
> +
>   usb_chip[chip->index] = chip;
>   chip->num_interfaces++;
>   chip->probing = 0;
> @@ -616,6 +619,8 @@ static void usb_audio_disconnect(struct usb_interface 
> *intf)
>   list_for_each(p, >midi_list) {
>   snd_usbmidi_disconnect(p);
>   }
> + /* delete mixer media resources */
> + media_mixer_delete(chip);
>   /* release mixer resources */
>   list_for_each_entry(mixer, >mixer_list, list) {
>   snd_usb_mixer_disconnect(mixer);
> diff --git a/sound/usb/media.c b/sound/usb/media.c
> index 0cbfee6..a26ea8b 100644
> --- a/sound/usb/media.c
> +++ b/sound/usb/media.c
> @@ -199,4 +199,93 @@ void media_stop_pipeline(struct snd_usb_substream *subs)
>   if (mctl)
>   media_disable_source(mctl);
>  }
> +
> +int media_mixer_init(struct snd_usb_audio *chip)
> +{
> + struct device *ctl_dev = >card->ctl_dev;
> + struct media_intf_devnode *ctl_intf;
> + struct usb_mixer_interface *mixer;
> + struct media_device *mdev;
> + struct media_mixer_ctl *mctl;
> + u32 intf_type = MEDIA_INTF_T_ALSA_CONTROL;
> + int ret;
> +
> + mdev = media_device_find_devres(>dev->dev);
> + if (!mdev)
> + return -ENODEV;
> +
> + ctl_intf = (struct media_intf_devnode *) chip->ctl_intf_media_devnode;

Why do we need cast?  Can't chip->ctl_intf_media_devnode itself be
struct media_intf_devndoe pointer?


> + if (!ctl_intf) {
> + ctl_intf = (void *) media_devnode_create(mdev,
> +  intf_type, 0,
> +  MAJOR(ctl_dev->devt),
> +  MINOR(ctl_dev->devt));
> + if (!ctl_intf)
> + return -ENOMEM;
> + }

Is chip->ctl_intf_media_devnode assigned anywhere at all?

Not directly related with this patchset: the above uses
media_devnode_create(), which I assume it's a device-file
(major:minor) specific.  What if sound hardware with multiple codecs
and so on in general?


> +
> + list_for_each_entry(mixer, >mixer_list, list) {
> +
> + if (mixer->media_mixer_ctl)
> + continue;
> +
> + /* allocate media_ctl */
> + mctl = kzalloc(sizeof(struct media_ctl), GFP_KERNEL);
> + if (!mctl)
> + return -ENOMEM;
> +
> + mixer->media_mixer_ctl = (void *) mctl;
> + mctl->media_dev = mdev;
> +
> + mctl->media_entity.function = MEDIA_ENT_F_AUDIO_MIXER;
> + mctl->media_entity.name = chip->card->mixername;
> + mctl->media_pad[0].flags = MEDIA_PAD_FL_SINK;
> + mctl->media_pad[1].flags = MEDIA_PAD_FL_SOURCE;
> + mctl->media_pad[2].flags = MEDIA_PAD_FL_SOURCE;
> + media_entity_init(>media_entity, MEDIA_MIXER_PAD_MAX,
> +   mctl->media_pad);
> + ret =  media_device_register_entity(mctl->media_dev,
> + >media_entity);
> + if (ret)
> + return ret;

Will the last (unfinished) mctl be freed properly in the error path?

> + mctl->intf_link = media_create_intf_link(>media_entity,
> +  _intf->intf,
> +  MEDIA_LNK_FL_ENABLED);
> + if (!mctl->intf_link) {
> + media_device_unregister_entity(>media_entity);
> + return -ENOMEM;

Ditto.

> + }
> + mctl->intf_devnode = ctl_intf;
> + }
> + return 0;
> +}
> +
> +void media_mixer_delete(struct snd_usb_audio *chip)
> +{
> + struct usb_mixer_interface *mixer;
> + struct media_device *mdev;
> +
> + mdev = media_device_find_devres(>dev->dev);
> + if (!mdev)
> + 

[PATCH] [media] c8sectpfe: Remove select on CONFIG_FW_LOADER_USER_HELPER_FALLBACK

2015-10-19 Thread Takashi Iwai
c8sectpfe driver selects CONFIG_FW_LOADER_USER_HELPER_FALLBACK by some
reason, but this option is known to be harmful, leading to minutes of
stalls at boot time.  The option was intended for only compatibility
for an old exotic system that mandates the udev interaction, and not a
thing a driver selects by itself.  Let's remove it.

Fixes: 850a3f7d5911 ('[media] c8sectpfe: Add Kconfig and Makefile for the 
driver')
Signed-off-by: Takashi Iwai <ti...@suse.de>
---
 drivers/media/platform/sti/c8sectpfe/Kconfig | 1 -
 1 file changed, 1 deletion(-)

diff --git a/drivers/media/platform/sti/c8sectpfe/Kconfig 
b/drivers/media/platform/sti/c8sectpfe/Kconfig
index 641ad8f34956..7420a50572d3 100644
--- a/drivers/media/platform/sti/c8sectpfe/Kconfig
+++ b/drivers/media/platform/sti/c8sectpfe/Kconfig
@@ -3,7 +3,6 @@ config DVB_C8SECTPFE
depends on PINCTRL && DVB_CORE && I2C
depends on ARCH_STI || ARCH_MULTIPLATFORM || COMPILE_TEST
select FW_LOADER
-   select FW_LOADER_USER_HELPER_FALLBACK
select DEBUG_FS
select DVB_LNBP21 if MEDIA_SUBDRV_AUTOSELECT
select DVB_STV090x if MEDIA_SUBDRV_AUTOSELECT
-- 
2.6.1

--
To unsubscribe from this list: send the line "unsubscribe linux-media" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: Linux 4.2 ALSA snd-usb-audio inconsistent lock state warn in PCM nonatomic mode

2015-08-31 Thread Takashi Iwai
On Tue, 01 Sep 2015 00:48:30 +0200,
Shuah Khan wrote:
> 
> Hi Takashi,
> 
> I am seeing the following inconsistent lock state warning when PCM
> is run in nonatomic mode. This is on 4.2.0 and with the following
> change to force PCM on nonatomic mode:
> 
> diff --git a/sound/usb/stream.c b/sound/usb/stream.c
> index 310a382..16bbb71 100644
> --- a/sound/usb/stream.c
> +++ b/sound/usb/stream.c
> @@ -370,6 +370,7 @@ int snd_usb_add_audio_stream(struct snd_usb_audio *chip,
> pcm->private_data = as;
> pcm->private_free = snd_usb_audio_pcm_free;
> pcm->info_flags = 0;
> +   pcm->nonatomic = true;
> if (chip->pcm_devs > 0)
> sprintf(pcm->name, "USB Audio #%d", chip->pcm_devs);
> else
> 
> The device Bus 003 Device 002: ID 2040:7200 Hauppauge
> Please let me know if you need more information and any ideas on
> how to fix this problem.

The USB-audio can't be used in the non-atomic mode.
snd_pcm_period_elapsed() is handled in the complete callback that is
already atomic.


Takashi

> 
> thanks,
> -- Shuah
> 
> [  120.283960] =
> [  120.283964] [ INFO: inconsistent lock state ]
> [  120.283968] 4.2.0+ #29 Not tainted
> [  120.283972] -
> [  120.283975] inconsistent {HARDIRQ-ON-W} -> {IN-HARDIRQ-W} usage.
> [  120.283980] swapper/1/0 [HC1[1]:SC0[0]:HE0:SE1] takes:
> [  120.283983]  (&(>lock)->rlock){?.+...}, at:
> [] retire_capture_urb+0x140/0x2b0 [snd_usb_audio]
> [  120.284005] {HARDIRQ-ON-W} state was registered at:
> [  120.284008]   [] __lock_acquire+0xc50/0x2380
> [  120.284016]   [] lock_acquire+0xb1/0x130
> [  120.284022]   [] _raw_spin_lock+0x31/0x40
> [  120.284028]   [] snd_usb_pcm_pointer+0x5d/0xc0
> [snd_usb_audio]
> [  120.284040]   [] snd_pcm_update_hw_ptr0+0x38/0x3a0
> [snd_pcm]
> [  120.284052]   [] snd_pcm_update_hw_ptr+0x10/0x20
> [snd_pcm]
> [  120.284063]   [] snd_pcm_hwsync+0x45/0xa0 [snd_pcm]
> [  120.284071]   [] snd_pcm_common_ioctl1+0x277/0xce0
> [snd_pcm]
> [  120.284081]   [] snd_pcm_capture_ioctl1+0x1be/0x2d0
> [snd_pcm]
> [  120.284090]   [] snd_pcm_capture_ioctl+0x34/0x40
> [snd_pcm]
> [  120.284100]   [] do_vfs_ioctl+0x301/0x560
> [  120.284107]   [] SyS_ioctl+0x79/0x90
> [  120.284112]   [] entry_SYSCALL_64_fastpath+0x12/0x6f
> [  120.284119] irq event stamp: 823304
> [  120.284122] hardirqs last  enabled at (823301): []
> cpuidle_enter_state+0xed/0x230
> [  120.284129] hardirqs last disabled at (823302): []
> common_interrupt+0x68/0x6d
> [  120.284135] softirqs last  enabled at (823304): []
> _local_bh_enable+0x21/0x50
> [  120.284139] softirqs last disabled at (823303): []
> irq_enter+0x4c/0x70
> [  120.284143]
> other info that might help us debug this:
> [  120.284146]  Possible unsafe locking scenario:
> 
> [  120.284149]CPU0
> [  120.284150]
> [  120.284152]   lock(&(>lock)->rlock);
> [  120.284155]   
> [  120.284157] lock(&(>lock)->rlock);
> [  120.284160]
>  *** DEADLOCK ***
> [  120.284163] no locks held by swapper/1/0.
> [  120.284165]
> stack backtrace:
> [  120.284170] CPU: 1 PID: 0 Comm: swapper/1 Not tainted 4.2.0+ #29
> [  120.284173] Hardware name: Hewlett-Packard HP ProBook 6475b/180F,
> BIOS 68TTU Ver. F.04 08/03/2012
> [  120.284176]  828d5630 88023ec83a68 817f4ea0
> 0007
> [  120.284181]  880235a6a500 88023ec83ac8 810ad97f
> 
> [  120.284186]   88020001 810134df
> 827c5390
> [  120.284192] Call Trace:
> [  120.284194][] dump_stack+0x45/0x57
> [  120.284203]  [] print_usage_bug+0x1ff/0x210
> [  120.284209]  [] ? save_stack_trace+0x2f/0x50
> [  120.284214]  [] mark_lock+0x66e/0x6f0
> [  120.284218]  [] ?
> print_shortest_lock_dependencies+0x1d0/0x1d0
> [  120.284222]  [] __lock_acquire+0xdcb/0x2380
> [  120.284226]  [] ? __enqueue_entity+0x6c/0x70
> [  120.284230]  [] ? __lock_is_held+0x4d/0x70
> [  120.284234]  [] ? __lock_is_held+0x4d/0x70
> [  120.284238]  [] ? __lock_is_held+0x4d/0x70
> [  120.284242]  [] ? __lock_is_held+0x4d/0x70
> [  120.284246]  [] lock_acquire+0xb1/0x130
> [  120.284256]  [] ? retire_capture_urb+0x140/0x2b0
> [snd_usb_audio]
> [  120.284261]  [] _raw_spin_lock_irqsave+0x3c/0x50
> [  120.284270]  [] ? retire_capture_urb+0x140/0x2b0
> [snd_usb_audio]
> [  120.284276]  [] ? usb_hcd_get_frame_number+0x25/0x30
> [  120.284285]  [] retire_capture_urb+0x140/0x2b0
> [snd_usb_audio]
> [  120.284294]  [] snd_complete_urb+0x13c/0x250
> [snd_usb_audio]
> [  120.284298]  [] __usb_hcd_giveback_urb+0x72/0x110
> [  120.284303]  [] usb_hcd_giveback_urb+0x43/0x140
> [  120.284307]  [] xhci_irq+0xd42/0x1fc0
> [  120.284312]  [] xhci_msi_irq+0x11/0x20
> [  120.284317]  [] handle_irq_event_percpu+0x80/0x1a0
> [  120.284322]  [] handle_irq_event+0x4a/0x70
> [  120.284325]  [] ? handle_edge_irq+0x24/0x150
> [  120.284329]  [] handle_edge_irq+0x81/0x150
> [  120.284333]  [] handle_irq+0x25/0x40
> [  120.284337] 

Re: [PATCH 7/7] sound/usb: Update ALSA driver to use Managed Media Controller API

2015-07-20 Thread Takashi Iwai
On Mon, 20 Jul 2015 10:47:46 +0200,
Dan Carpenter wrote:
 
 On Tue, Jul 14, 2015 at 06:34:06PM -0600, Shuah Khan wrote:
  +   ret = media_entity_setup_link(link, flags);
  +   if (ret) {
  +   dev_err(mctl-media_dev-dev,
  +   Couldn't change tuner link,
  +   %s-%s to %s. Error %d\n,
 
 Add a space after link.
 
   Couldn't change tuner link ,
   %s-%s to %s. Error %d\n,

Such a message string would be better to be in a single line even if
it's over 80 chars.  Otherwise it becomes hard to grep.


thanks,

Takashi
--
To unsubscribe from this list: send the line unsubscribe linux-media in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH 2/2] sound/usb: Update ALSA driver to use media controller API

2015-05-27 Thread Takashi Iwai
At Fri,  8 May 2015 13:31:31 -0600,
Shuah Khan wrote:
 
 Change ALSA driver to use media controller API to share tuner
 with DVB and V4L2 drivers that control AU0828 media device.
 Media device is created based on a newly added field value
 in the struct snd_usb_audio_quirk. Using this approach, the
 media controller API usage can be added for a specific device.
 In this patch, media controller API is enabled for AU0828 hw.
 snd_usb_create_quirk() will check this new field, if set will
 create a media device using media_device_get_dr() interface.
 media_device_get_dr() will allocate a new media device device
 resource or return an existing one if it exists. During probe,
 media usb driver could have created the media device. It will
 then register the media device if it isn't already registered.
 Media device unregister is done from usb_audio_disconnect().
 
 New fields to add support for media entity and links are
 added to struct snd_usb_substream. A new media entity for
 ALSA and a link from tuner entity to the newly registered
 ALSA entity are created from snd_usb_init_substream() and
 removed from free_substream(). The state is kept to indicate
 if tuner is linked. This is to account for case when tuner
 entity doesn't exist. Media pipeline gets started to mark
 the tuner busy from snd_usb_substream_capture_trigger in
 response to SNDRV_PCM_TRIGGER_START and pipeline is stopped
 in response to SNDRV_PCM_TRIGGER_STOP. snd_usb_pcm_close()
 stops pipeline to cover the case when SNDRV_PCM_TRIGGER_STOP
 isn't issued. Pipeline start and stop are done only when
 tuner_linked is set.
 
 Tested with and without CONFIG_MEDIA_CONTROLLER enabled.
 Tested tuner entity doesn't exist case as au0828 v4l2
 driver is the one that will create the tuner when it gets
 updated to use media controller API.

I guess it gets broken when CONFIG_MEDIA_SUPPORT=m while
CONFIG_SND*=y.  So, it should be compiled in only when the media
support is built-in or both sound and media are module, i.e.

#ifdef CONFIG_MEDIA_CONTROLLER
#if defined(CONFIG_MEDIA_SUPPORT) || \
(defined(CONFIG_MEDIA_SUPPORT_MODULE)  defined(MODULE))
#define I_CAN_USE_MEDIA_CONTROLLER
#endif
#endif

 Signed-off-by: Shuah Khan shua...@osg.samsung.com
 ---
  sound/usb/card.c |  5 +
  sound/usb/card.h | 12 ++
  sound/usb/pcm.c  | 23 ++-
  sound/usb/quirks-table.h |  1 +
  sound/usb/quirks.c   | 58 
 +++-
  sound/usb/quirks.h   |  6 +
  sound/usb/stream.c   | 40 +
  sound/usb/usbaudio.h |  1 +
  8 files changed, 144 insertions(+), 2 deletions(-)
 
 diff --git a/sound/usb/card.c b/sound/usb/card.c
 index 1fab977..587fc24 100644
 --- a/sound/usb/card.c
 +++ b/sound/usb/card.c
 @@ -621,6 +621,11 @@ static void usb_audio_disconnect(struct usb_interface 
 *intf)
   }
   }
  
 + /* Nice to check quirk  quirk-media_device
 +  * need some special handlings. Doesn't look like
 +  * we have access to quirk here */
 + media_device_delete(intf);

This should be called once, so better in if (!was_shutdown) block, I
guess.

Apart from that, yes, a good way to call an optional destructor for
quirks would be better.


   chip-num_interfaces--;
   if (chip-num_interfaces = 0) {
   usb_chip[chip-index] = NULL;
 diff --git a/sound/usb/card.h b/sound/usb/card.h
 index ef580b4..477bdcd 100644
 --- a/sound/usb/card.h
 +++ b/sound/usb/card.h
 @@ -1,6 +1,11 @@
  #ifndef __USBAUDIO_CARD_H
  #define __USBAUDIO_CARD_H
  
 +#ifdef CONFIG_MEDIA_CONTROLLER
 +#include media/media-device.h
 +#include media/media-entity.h
 +#endif
 +
  #define MAX_NR_RATES 1024
  #define MAX_PACKS6   /* per URB */
  #define MAX_PACKS_HS (MAX_PACKS * 8) /* in high speed mode */
 @@ -155,6 +160,13 @@ struct snd_usb_substream {
   } dsd_dop;
  
   bool trigger_tstamp_pending_update; /* trigger timestamp being updated 
 from initial estimate */
 +#ifdef CONFIG_MEDIA_CONTROLLER
 + struct media_device *media_dev;
 + struct media_entity media_entity;
 + struct media_pad media_pads;
 + struct media_pipeline media_pipe;
 + bool   tuner_linked;
 +#endif

Maybe a slightly better idea is to allocate these in a new record and
stores the pointer in stream-media_ctl or whatever new field.
Then, a check like
if (subs-tuner_linked)
can be replaced with
if (subs-media_ctl)

The whole media-specific stuff can be gathered in a single file,
e.g. sound/usb/media.c, and there you can define the struct.


  };
  
  struct snd_usb_stream {
 diff --git a/sound/usb/pcm.c b/sound/usb/pcm.c
 index b4ef410..c2a40a9 100644
 --- a/sound/usb/pcm.c
 +++ b/sound/usb/pcm.c
 @@ -1225,6 +1225,10 @@ static int snd_usb_pcm_close(struct snd_pcm_substream 
 *substream, int direction)
  
   subs-pcm_substream = NULL;
   snd_usb_autosuspend(subs-stream-chip);
 +#ifdef CONFIG_MEDIA_CONTROLLER

Re: DVB suspend/resume regression on 3.19

2015-02-16 Thread Takashi Iwai
At Fri, 13 Feb 2015 16:12:40 +0100,
Takashi Iwai wrote:
 
 At Fri, 13 Feb 2015 12:41:25 -0200,
 Mauro Carvalho Chehab wrote:
  
  Em Fri, 13 Feb 2015 15:02:42 +0100
  Takashi Iwai ti...@suse.de escreveu:
  
   At Mon, 09 Feb 2015 11:59:07 +0100,
   Takashi Iwai wrote:

Hi,

we've got a bug report about the suspend/resume regression of DVB
device with 3.19.  The symptom is VLC doesn't work after S3 or S4
resume.  strace shows that /dev/dvb/adaptor0/dvr returns -ENODEV.

The reporter confirmed that 3.18 works fine, so the regression must be
in 3.19.

There is a relevant kernel warning while suspending:

 WARNING: CPU: 1 PID: 3603 at ../kernel/module.c:1001 
module_put+0xc7/0xd0()
 Workqueue: events_unbound async_run_entry_fn
   81a45779 81664f12 
  81062381  a051eea0 8800ca369278
  a051a068 8800c0a18090 810dfb47 
 Call Trace:
  [810055ac] dump_trace+0x8c/0x340
  [81005903] show_stack_log_lvl+0xa3/0x190
  [81007061] show_stack+0x21/0x50
  [81664f12] dump_stack+0x47/0x67
  [81062381] warn_slowpath_common+0x81/0xb0
  [810dfb47] module_put+0xc7/0xd0
  [a04d98d1] dvb_usb_adapter_frontend_exit+0x41/0x60 [dvb_usb]
  [a04d8451] dvb_usb_exit+0x31/0xa0 [dvb_usb]
  [a04d84fb] dvb_usb_device_exit+0x3b/0x50 [dvb_usb]
  [814cefad] usb_unbind_interface+0x1ed/0x2c0
  [8145ceae] __device_release_driver+0x7e/0x100
  [8145cf52] device_release_driver+0x22/0x30
  [814cf13d] usb_forced_unbind_intf+0x2d/0x60
  [814cf3c3] usb_suspend+0x73/0x130
  [814bd453] usb_dev_freeze+0x13/0x20
  [81468fca] dpm_run_callback+0x4a/0x150
  [81469c81] __device_suspend+0x121/0x350
  [81469ece] async_suspend+0x1e/0xa0
  [81081e63] async_run_entry_fn+0x43/0x150
  [81079e72] process_one_work+0x142/0x3f0
  [8107a234] worker_thread+0x114/0x460
  [8107f3b1] kthread+0xc1/0xe0
  [8166b77c] ret_from_fork+0x7c/0xb0

So something went wrong in module refcount, which likely leads to
disabling the device and returning -ENODEV in the end.

Does this ring a bell to you guys?

The hardware details and logs are found in the URL below:
  https://bugzilla.novell.com/show_bug.cgi?id=916577
   
   I wonder whether no one hits the same problem...?
  
  Hi Takashi,
  
  There were no recent changes at dvb-usb core or at the dtt200u.c driver.
  So, I don't think that the regression was caused by a change at the media
  subsystem. Yet, we've added some patches to fix suspend/resume at the
  DVB core, but they basically add a new set of optional callbacks. So, it
  should not cause any regression.
  
  The changeset in question is 59d7889ae49f6e3e9d9cff8c0de7ad95d9ca068b.
  
 Hm, is this commit really merged between 3.18 and 3.19?
 
  From those messages:
  
  2015-02-06T15:30:47.468258+01:00 linux-z24t kernel: [  150.552119] dvb-usb: 
  downloading firmware from file 'dvb-usb-wt220u-fc03.fw'
  2015-02-06T15:30:47.468827+01:00 linux-z24t mtp-probe: checking bus 1, 
  device 5: /sys/devices/pci:00/:00:1d.7/usb1/1-4
  2015-02-06T15:30:47.879878+01:00 linux-z24t mtp-probe: bus: 1, device: 5 
  was not an MTP device
  2015-02-06T15:30:47.880192+01:00 linux-z24t kernel: [  151.992993] usb 1-4: 
  USB disconnect, device number 5
  2015-02-06T15:30:47.880839+01:00 linux-z24t kernel: [  151.993076] dvb-usb: 
  generic DVB-USB module successfully deinitialized and disconnected.
  
  I _suspect_ that dvb_usb_download_firmware() failed to load the firmware
  file.
  
  That problem actually looks like a recently discovered issue:t
  request_firmware() fails during resume on some systems. What
  seems to happen in this case is that the media drivers are resumed
  _before_ mounting the partition where the firmware file is hosted.
  
  Yet, in this case, it should be printing:
  did not find the firmware file.
 
 Right.  This makes me wonder, too.
 
  I would add a test patch in order to print the return code from
  dvb_usb_download_firmware(), in order to see if it succeeds or
  not, e. g. something like the patch below, and then try to narrow
  down where it is failing, assuming that the new message will be printed.
  
  If nothing gets printed, then I would try to discover why the USB
  stack disconnected the device. Perhaps an ehci/xhci bug?
 
 OK, I'll give a test kernel to report.

The patched kernel didn't show the message.  So it's not about the
firmware load failure, apparently.  Any other point to check?


Takashi
--
To unsubscribe from this list: send the line unsubscribe linux-media in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http

Re: DVB suspend/resume regression on 3.19

2015-02-13 Thread Takashi Iwai
At Mon, 09 Feb 2015 11:59:07 +0100,
Takashi Iwai wrote:
 
 Hi,
 
 we've got a bug report about the suspend/resume regression of DVB
 device with 3.19.  The symptom is VLC doesn't work after S3 or S4
 resume.  strace shows that /dev/dvb/adaptor0/dvr returns -ENODEV.
 
 The reporter confirmed that 3.18 works fine, so the regression must be
 in 3.19.
 
 There is a relevant kernel warning while suspending:
 
  WARNING: CPU: 1 PID: 3603 at ../kernel/module.c:1001 module_put+0xc7/0xd0()
  Workqueue: events_unbound async_run_entry_fn
    81a45779 81664f12 
   81062381  a051eea0 8800ca369278
   a051a068 8800c0a18090 810dfb47 
  Call Trace:
   [810055ac] dump_trace+0x8c/0x340
   [81005903] show_stack_log_lvl+0xa3/0x190
   [81007061] show_stack+0x21/0x50
   [81664f12] dump_stack+0x47/0x67
   [81062381] warn_slowpath_common+0x81/0xb0
   [810dfb47] module_put+0xc7/0xd0
   [a04d98d1] dvb_usb_adapter_frontend_exit+0x41/0x60 [dvb_usb]
   [a04d8451] dvb_usb_exit+0x31/0xa0 [dvb_usb]
   [a04d84fb] dvb_usb_device_exit+0x3b/0x50 [dvb_usb]
   [814cefad] usb_unbind_interface+0x1ed/0x2c0
   [8145ceae] __device_release_driver+0x7e/0x100
   [8145cf52] device_release_driver+0x22/0x30
   [814cf13d] usb_forced_unbind_intf+0x2d/0x60
   [814cf3c3] usb_suspend+0x73/0x130
   [814bd453] usb_dev_freeze+0x13/0x20
   [81468fca] dpm_run_callback+0x4a/0x150
   [81469c81] __device_suspend+0x121/0x350
   [81469ece] async_suspend+0x1e/0xa0
   [81081e63] async_run_entry_fn+0x43/0x150
   [81079e72] process_one_work+0x142/0x3f0
   [8107a234] worker_thread+0x114/0x460
   [8107f3b1] kthread+0xc1/0xe0
   [8166b77c] ret_from_fork+0x7c/0xb0
 
 So something went wrong in module refcount, which likely leads to
 disabling the device and returning -ENODEV in the end.
 
 Does this ring a bell to you guys?
 
 The hardware details and logs are found in the URL below:
   https://bugzilla.novell.com/show_bug.cgi?id=916577

I wonder whether no one hits the same problem...?


Takashi
--
To unsubscribe from this list: send the line unsubscribe linux-media in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: DVB suspend/resume regression on 3.19

2015-02-13 Thread Takashi Iwai
At Fri, 13 Feb 2015 12:41:25 -0200,
Mauro Carvalho Chehab wrote:
 
 Em Fri, 13 Feb 2015 15:02:42 +0100
 Takashi Iwai ti...@suse.de escreveu:
 
  At Mon, 09 Feb 2015 11:59:07 +0100,
  Takashi Iwai wrote:
   
   Hi,
   
   we've got a bug report about the suspend/resume regression of DVB
   device with 3.19.  The symptom is VLC doesn't work after S3 or S4
   resume.  strace shows that /dev/dvb/adaptor0/dvr returns -ENODEV.
   
   The reporter confirmed that 3.18 works fine, so the regression must be
   in 3.19.
   
   There is a relevant kernel warning while suspending:
   
WARNING: CPU: 1 PID: 3603 at ../kernel/module.c:1001 
   module_put+0xc7/0xd0()
Workqueue: events_unbound async_run_entry_fn
  81a45779 81664f12 
 81062381  a051eea0 8800ca369278
 a051a068 8800c0a18090 810dfb47 
Call Trace:
 [810055ac] dump_trace+0x8c/0x340
 [81005903] show_stack_log_lvl+0xa3/0x190
 [81007061] show_stack+0x21/0x50
 [81664f12] dump_stack+0x47/0x67
 [81062381] warn_slowpath_common+0x81/0xb0
 [810dfb47] module_put+0xc7/0xd0
 [a04d98d1] dvb_usb_adapter_frontend_exit+0x41/0x60 [dvb_usb]
 [a04d8451] dvb_usb_exit+0x31/0xa0 [dvb_usb]
 [a04d84fb] dvb_usb_device_exit+0x3b/0x50 [dvb_usb]
 [814cefad] usb_unbind_interface+0x1ed/0x2c0
 [8145ceae] __device_release_driver+0x7e/0x100
 [8145cf52] device_release_driver+0x22/0x30
 [814cf13d] usb_forced_unbind_intf+0x2d/0x60
 [814cf3c3] usb_suspend+0x73/0x130
 [814bd453] usb_dev_freeze+0x13/0x20
 [81468fca] dpm_run_callback+0x4a/0x150
 [81469c81] __device_suspend+0x121/0x350
 [81469ece] async_suspend+0x1e/0xa0
 [81081e63] async_run_entry_fn+0x43/0x150
 [81079e72] process_one_work+0x142/0x3f0
 [8107a234] worker_thread+0x114/0x460
 [8107f3b1] kthread+0xc1/0xe0
 [8166b77c] ret_from_fork+0x7c/0xb0
   
   So something went wrong in module refcount, which likely leads to
   disabling the device and returning -ENODEV in the end.
   
   Does this ring a bell to you guys?
   
   The hardware details and logs are found in the URL below:
 https://bugzilla.novell.com/show_bug.cgi?id=916577
  
  I wonder whether no one hits the same problem...?
 
 Hi Takashi,
 
 There were no recent changes at dvb-usb core or at the dtt200u.c driver.
 So, I don't think that the regression was caused by a change at the media
 subsystem. Yet, we've added some patches to fix suspend/resume at the
 DVB core, but they basically add a new set of optional callbacks. So, it
 should not cause any regression.
 
 The changeset in question is 59d7889ae49f6e3e9d9cff8c0de7ad95d9ca068b.
 
Hm, is this commit really merged between 3.18 and 3.19?

 From those messages:
 
 2015-02-06T15:30:47.468258+01:00 linux-z24t kernel: [  150.552119] dvb-usb: 
 downloading firmware from file 'dvb-usb-wt220u-fc03.fw'
 2015-02-06T15:30:47.468827+01:00 linux-z24t mtp-probe: checking bus 1, device 
 5: /sys/devices/pci:00/:00:1d.7/usb1/1-4
 2015-02-06T15:30:47.879878+01:00 linux-z24t mtp-probe: bus: 1, device: 5 was 
 not an MTP device
 2015-02-06T15:30:47.880192+01:00 linux-z24t kernel: [  151.992993] usb 1-4: 
 USB disconnect, device number 5
 2015-02-06T15:30:47.880839+01:00 linux-z24t kernel: [  151.993076] dvb-usb: 
 generic DVB-USB module successfully deinitialized and disconnected.
 
 I _suspect_ that dvb_usb_download_firmware() failed to load the firmware
 file.
 
 That problem actually looks like a recently discovered issue:t
 request_firmware() fails during resume on some systems. What
 seems to happen in this case is that the media drivers are resumed
 _before_ mounting the partition where the firmware file is hosted.
 
 Yet, in this case, it should be printing:
   did not find the firmware file.

Right.  This makes me wonder, too.

 I would add a test patch in order to print the return code from
 dvb_usb_download_firmware(), in order to see if it succeeds or
 not, e. g. something like the patch below, and then try to narrow
 down where it is failing, assuming that the new message will be printed.
 
 If nothing gets printed, then I would try to discover why the USB
 stack disconnected the device. Perhaps an ehci/xhci bug?

OK, I'll give a test kernel to report.


Thanks!

Takashi
--
To unsubscribe from this list: send the line unsubscribe linux-media in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


DVB suspend/resume regression on 3.19

2015-02-09 Thread Takashi Iwai
Hi,

we've got a bug report about the suspend/resume regression of DVB
device with 3.19.  The symptom is VLC doesn't work after S3 or S4
resume.  strace shows that /dev/dvb/adaptor0/dvr returns -ENODEV.

The reporter confirmed that 3.18 works fine, so the regression must be
in 3.19.

There is a relevant kernel warning while suspending:

 WARNING: CPU: 1 PID: 3603 at ../kernel/module.c:1001 module_put+0xc7/0xd0()
 Workqueue: events_unbound async_run_entry_fn
   81a45779 81664f12 
  81062381  a051eea0 8800ca369278
  a051a068 8800c0a18090 810dfb47 
 Call Trace:
  [810055ac] dump_trace+0x8c/0x340
  [81005903] show_stack_log_lvl+0xa3/0x190
  [81007061] show_stack+0x21/0x50
  [81664f12] dump_stack+0x47/0x67
  [81062381] warn_slowpath_common+0x81/0xb0
  [810dfb47] module_put+0xc7/0xd0
  [a04d98d1] dvb_usb_adapter_frontend_exit+0x41/0x60 [dvb_usb]
  [a04d8451] dvb_usb_exit+0x31/0xa0 [dvb_usb]
  [a04d84fb] dvb_usb_device_exit+0x3b/0x50 [dvb_usb]
  [814cefad] usb_unbind_interface+0x1ed/0x2c0
  [8145ceae] __device_release_driver+0x7e/0x100
  [8145cf52] device_release_driver+0x22/0x30
  [814cf13d] usb_forced_unbind_intf+0x2d/0x60
  [814cf3c3] usb_suspend+0x73/0x130
  [814bd453] usb_dev_freeze+0x13/0x20
  [81468fca] dpm_run_callback+0x4a/0x150
  [81469c81] __device_suspend+0x121/0x350
  [81469ece] async_suspend+0x1e/0xa0
  [81081e63] async_run_entry_fn+0x43/0x150
  [81079e72] process_one_work+0x142/0x3f0
  [8107a234] worker_thread+0x114/0x460
  [8107f3b1] kthread+0xc1/0xe0
  [8166b77c] ret_from_fork+0x7c/0xb0

So something went wrong in module refcount, which likely leads to
disabling the device and returning -ENODEV in the end.

Does this ring a bell to you guys?

The hardware details and logs are found in the URL below:
  https://bugzilla.novell.com/show_bug.cgi?id=916577


thanks,

Takashi
--
To unsubscribe from this list: send the line unsubscribe linux-media in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH 1/2] [media] sound: simplify au0828 quirk table

2014-10-30 Thread Takashi Iwai
At Thu, 30 Oct 2014 08:53:04 -0200,
Mauro Carvalho Chehab wrote:
 
 From: Mauro Carvalho Chehab m.che...@samsung.com
 
 Add a macro to simplify au0828 quirk table. That makes easier
 to check it against the USB IDs at drivers/media/usb/au0828-card.c
 
 Cc: sta...@vger.kernel.org
 Signed-off-by: Mauro Carvalho Chehab m.che...@samsung.com
 Signed-off-by: Mauro Carvalho Chehab mche...@osg.samsung.com

Which sign-off should I take?  Judging from the author line, the
former one?  The second patch had only s-o-b from @samsung.com.


thanks,

Takashi

 
 diff --git a/sound/usb/quirks-table.h b/sound/usb/quirks-table.h
 index c657752a420c..5ae1d02d17a3 100644
 --- a/sound/usb/quirks-table.h
 +++ b/sound/usb/quirks-table.h
 @@ -2804,133 +2804,37 @@ YAMAHA_DEVICE(0x7010, UB99),
   }
  },
  
 -/* Hauppauge HVR-950Q and HVR-850 */
 -{
 - USB_DEVICE_VENDOR_SPEC(0x2040, 0x7200),
 - .match_flags = USB_DEVICE_ID_MATCH_DEVICE |
 -USB_DEVICE_ID_MATCH_INT_CLASS |
 -USB_DEVICE_ID_MATCH_INT_SUBCLASS,
 - .bInterfaceClass = USB_CLASS_AUDIO,
 - .bInterfaceSubClass = USB_SUBCLASS_AUDIOCONTROL,
 - .driver_info = (unsigned long) (const struct snd_usb_audio_quirk) {
 - .vendor_name = Hauppauge,
 - .product_name = HVR-950Q,
 - .ifnum = QUIRK_ANY_INTERFACE,
 - .type = QUIRK_AUDIO_ALIGN_TRANSFER,
 - }
 -},
 -{
 - USB_DEVICE_VENDOR_SPEC(0x2040, 0x7210),
 - .match_flags = USB_DEVICE_ID_MATCH_DEVICE |
 -USB_DEVICE_ID_MATCH_INT_CLASS |
 -USB_DEVICE_ID_MATCH_INT_SUBCLASS,
 - .bInterfaceClass = USB_CLASS_AUDIO,
 - .bInterfaceSubClass = USB_SUBCLASS_AUDIOCONTROL,
 - .driver_info = (unsigned long) (const struct snd_usb_audio_quirk) {
 - .vendor_name = Hauppauge,
 - .product_name = HVR-950Q,
 - .ifnum = QUIRK_ANY_INTERFACE,
 - .type = QUIRK_AUDIO_ALIGN_TRANSFER,
 - }
 -},
 -{
 - USB_DEVICE_VENDOR_SPEC(0x2040, 0x7217),
 - .match_flags = USB_DEVICE_ID_MATCH_DEVICE |
 -USB_DEVICE_ID_MATCH_INT_CLASS |
 -USB_DEVICE_ID_MATCH_INT_SUBCLASS,
 - .bInterfaceClass = USB_CLASS_AUDIO,
 - .bInterfaceSubClass = USB_SUBCLASS_AUDIOCONTROL,
 - .driver_info = (unsigned long) (const struct snd_usb_audio_quirk) {
 - .vendor_name = Hauppauge,
 - .product_name = HVR-950Q,
 - .ifnum = QUIRK_ANY_INTERFACE,
 - .type = QUIRK_AUDIO_ALIGN_TRANSFER,
 - }
 -},
 -{
 - USB_DEVICE_VENDOR_SPEC(0x2040, 0x721b),
 - .match_flags = USB_DEVICE_ID_MATCH_DEVICE |
 -USB_DEVICE_ID_MATCH_INT_CLASS |
 -USB_DEVICE_ID_MATCH_INT_SUBCLASS,
 - .bInterfaceClass = USB_CLASS_AUDIO,
 - .bInterfaceSubClass = USB_SUBCLASS_AUDIOCONTROL,
 - .driver_info = (unsigned long) (const struct snd_usb_audio_quirk) {
 - .vendor_name = Hauppauge,
 - .product_name = HVR-950Q,
 - .ifnum = QUIRK_ANY_INTERFACE,
 - .type = QUIRK_AUDIO_ALIGN_TRANSFER,
 - }
 -},
 -{
 - USB_DEVICE_VENDOR_SPEC(0x2040, 0x721e),
 - .match_flags = USB_DEVICE_ID_MATCH_DEVICE |
 -USB_DEVICE_ID_MATCH_INT_CLASS |
 -USB_DEVICE_ID_MATCH_INT_SUBCLASS,
 - .bInterfaceClass = USB_CLASS_AUDIO,
 - .bInterfaceSubClass = USB_SUBCLASS_AUDIOCONTROL,
 - .driver_info = (unsigned long) (const struct snd_usb_audio_quirk) {
 - .vendor_name = Hauppauge,
 - .product_name = HVR-950Q,
 - .ifnum = QUIRK_ANY_INTERFACE,
 - .type = QUIRK_AUDIO_ALIGN_TRANSFER,
 - }
 -},
 -{
 - USB_DEVICE_VENDOR_SPEC(0x2040, 0x721f),
 - .match_flags = USB_DEVICE_ID_MATCH_DEVICE |
 -USB_DEVICE_ID_MATCH_INT_CLASS |
 -USB_DEVICE_ID_MATCH_INT_SUBCLASS,
 - .bInterfaceClass = USB_CLASS_AUDIO,
 - .bInterfaceSubClass = USB_SUBCLASS_AUDIOCONTROL,
 - .driver_info = (unsigned long) (const struct snd_usb_audio_quirk) {
 - .vendor_name = Hauppauge,
 - .product_name = HVR-950Q,
 - .ifnum = QUIRK_ANY_INTERFACE,
 - .type = QUIRK_AUDIO_ALIGN_TRANSFER,
 - }
 -},
 -{
 - USB_DEVICE_VENDOR_SPEC(0x2040, 0x7240),
 - .match_flags = USB_DEVICE_ID_MATCH_DEVICE |
 -USB_DEVICE_ID_MATCH_INT_CLASS |
 -USB_DEVICE_ID_MATCH_INT_SUBCLASS,
 - .bInterfaceClass = USB_CLASS_AUDIO,
 - .bInterfaceSubClass = USB_SUBCLASS_AUDIOCONTROL,
 - .driver_info = (unsigned long) (const struct snd_usb_audio_quirk) {
 - .vendor_name = Hauppauge,
 - .product_name = HVR-850,
 - .ifnum = QUIRK_ANY_INTERFACE,
 - .type = QUIRK_AUDIO_ALIGN_TRANSFER,
 - }
 -},
 -{
 - USB_DEVICE_VENDOR_SPEC(0x2040, 0x7280),
 - .match_flags = USB_DEVICE_ID_MATCH_DEVICE |
 -   

Re: [alsa-devel] [PATCH v2 5/6] sound/usb: pcm changes to use media token api

2014-10-26 Thread Takashi Iwai
At Sat, 25 Oct 2014 11:41:15 -0200,
Mauro Carvalho Chehab wrote:
 
 (re-sending from my third e-mail - somehow, the two emails I have at
  Samsung didn't seem to be delivering to vger.kernel.org today)
 
 Em Wed, 22 Oct 2014 14:26:41 -0500
 Pierre-Louis Bossart pierre-louis.boss...@linux.intel.com escreveu:
 
  On 10/21/14, 11:08 AM, Devin Heitmueller wrote:
   Sorry, I'm not convinced by that.  If the device has to be controlled
   exclusively, the right position is the open/close.  Otherwise, the
   program cannot know when it becomes inaccessible out of sudden during
   its operation.
  
   I can say that I've definitely seen cases where if you configure a
   device as the default capture device in PulseAudio, then pulse will
   continue to capture from it even if you're not actively capturing the
   audio from pulse.  I only spotted this because I had a USB analyzer on
   the device and was dumbfounded when the ISOC packets kept arriving
   even after I had closed VLC.
  
  this seems like a feature, not a bug. PulseAudio starts streaming before 
  clients push any data and likewise keeps sources active even after for 
  some time after clients stop recording. Closing VLC in your example 
  doesn't immediately close the ALSA device. look for 
  module-suspend-on-idle in your default.pa config file.
 
 This could be a feature for an audio capture device that is standalone,
 but for sure it isn't a feature for an audio capture device where the
 audio is only available if video is also being streamed.
 
 A V4L device with ALSA capture is a different beast than a standalone
 capture port. In a simplified way, it will basically follow the following
 state machine:
 
  +---+
  | start |
  +---+
|
|
v
  ++
  |  idle  | +
  ++  |
|^   ||
||   ||
v|   ||
  +---+  |   ||
  | configuration |  |   ||
  +---+  |   ||
||   ||
||   ||
v|   ||
  +---+  |   ||
   + |   streaming   | -+   ||
   |  +---+  ||
   ||||
   ||||
   |vv|
   |  +---+---++  |
   +- |   1   | suspended |  2 | -+
  +---+---++
 
 
 1) start state
 
 This is when the V4L2 device gots probed. It checks if the hardware is
 present and initializes some vars/registers, turning off everything
 that can be powered down.
 
 The tuner on put in sleep mode, analog audio/video decoders and the
 dvb frontend and demux are also turned off.
 
 2) idle state
 
 As the device is powered off, audio won't produce anything. 
 
 Depending on the device, reading for audio may return a sequence of 
 zeros, or may even fail, as the DMA engine is not ready yet for
 streaming.
 
 Also, the audio mixer is muted, but the audio input switch is on a
 random state.
 
 2) configuration state
 
 When V4L2 node device is opened and configured, the audio mixer will
 be switched to input audio from the same source of the video stream.
 The corresponding audio input is also unmuted. Almost all devices have 
 at least two audio/video inputs: TV TUNER and COMPOSITE. Other devices
 may also have S-VIDEO, COMPOSITE 2, RADIO TUNER, etc.
 
 If the device is set on TUNER mode, on modern devices, a tuner firmware
 will be loaded. That may require a long time. Typically, most devices
 take 1/2 seconds to load a firmware, but some devices may take up to 30
 seconds. The firmware may depend on the TV standard that will be used,
 so this can't be loaded at driver warm up state. 
 
 Also, the power consumption of the tuners is high (it can be ~100-200 mW
 or more when powered, and ~16mW when just I2C is powered). We don't want
 to keep it powered when the device is not used, as this spends battery.
 Also, the life of the device reduces a lot if we keep it always powered.
 
 During this stage, if an ALSA call is issued, it may interfere at the
 device settings and/or firmware load, with can cause the audio to fail. 
 On such cases, applications might need to close the V4L2 node and re-open
 again.
 
 3) streaming state
 
 The change to this staging requires a V4L2 ioctl.
 
 Please notice, however, that some apps will open the audio device before
 the V4L2 node, while others will open it after that.
 
 In any case, audio will only start to produce data after the V4L2 ioctl
 at V4L2 that starts the DMA engine there.
 
 After that ioctl:
  - Audio PCM capture will work;
  - The mixers will be in a good state: unmuted, 

[PATCH] [media] uvc: Fix destruction order in uvc_delete()

2014-10-24 Thread Takashi Iwai
We've got a bug report at disconnecting a Webcam, where the kernel
spews warnings like below:
  WARNING: CPU: 0 PID: 8385 at ../fs/sysfs/group.c:219 
sysfs_remove_group+0x87/0x90()
  sysfs group c0b2350c not found for kobject 'event3'
  CPU: 0 PID: 8385 Comm: queue2:src Not tainted 3.16.2-1.gdcee397-default #1
  Hardware name: ASUSTeK Computer INC. A7N8X-E/A7N8X-E, BIOS ASUS A7N8X-E 
Deluxe ACPI BIOS Rev 1013  11/12/2004
c08d0705 ddc75cbc c0718c5b ddc75ccc c024b654 c08c6d44 ddc75ce8 20c1
c08d0705 00db c03d1ec7 c03d1ec7 0009  c0b2350c d62c9064
ddc75cd4 c024b6a3 0009 ddc75ccc c08c6d44 ddc75ce8 ddc75cfc c03d1ec7
  Call Trace:
[c0205ba6] try_stack_unwind+0x156/0x170
[c02046f3] dump_trace+0x53/0x180
[c0205c06] show_trace_log_lvl+0x46/0x50
[c0204871] show_stack_log_lvl+0x51/0xe0
[c0205c67] show_stack+0x27/0x50
[c0718c5b] dump_stack+0x3e/0x4e
[c024b654] warn_slowpath_common+0x84/0xa0
[c024b6a3] warn_slowpath_fmt+0x33/0x40
[c03d1ec7] sysfs_remove_group+0x87/0x90
[c05a2c54] device_del+0x34/0x180
[c05e3989] evdev_disconnect+0x19/0x50
[c05e06fa] __input_unregister_device+0x9a/0x140
[c05e0845] input_unregister_device+0x45/0x80
[f854b1d6] uvc_delete+0x26/0x110 [uvcvideo]
[f84d66f8] v4l2_device_release+0x98/0xc0 [videodev]
[c05a25bb] device_release+0x2b/0x90
[c04ad8bf] kobject_cleanup+0x6f/0x1a0
[f84d5453] v4l2_release+0x43/0x70 [videodev]
[c0372f31] __fput+0xb1/0x1b0
[c02650c1] task_work_run+0x91/0xb0
[c024d845] do_exit+0x265/0x910
[c024df64] do_group_exit+0x34/0xa0
[c025a76f] get_signal_to_deliver+0x17f/0x590
[c0201b6a] do_signal+0x3a/0x960
[c02024f7] do_notify_resume+0x67/0x90
[c071ebb5] work_notifysig+0x30/0x3b
[b7739e60] 0xb7739e5f
   ---[ end trace b1e56095a485b631 ]---

The cause is that uvc_status_cleanup() is called after usb_put_*() in
uvc_delete().  usb_put_*() removes the sysfs parent and eventually
removes the children recursively, so the later device_del() can't find
its sysfs.  The fix is simply rearrange the call orders in
uvc_delete() so that the child is removed before the parent.

Bugzilla: https://bugzilla.suse.com/show_bug.cgi?id=897736
Reported-and-tested-by: Martin Pluskal mplus...@suse.com
Cc: sta...@vger.kernel.org
Signed-off-by: Takashi Iwai ti...@suse.de
---
 drivers/media/usb/uvc/uvc_driver.c | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/drivers/media/usb/uvc/uvc_driver.c 
b/drivers/media/usb/uvc/uvc_driver.c
index 7c8322d4fc63..3c07af96b30f 100644
--- a/drivers/media/usb/uvc/uvc_driver.c
+++ b/drivers/media/usb/uvc/uvc_driver.c
@@ -1623,12 +1623,12 @@ static void uvc_delete(struct uvc_device *dev)
 {
struct list_head *p, *n;
 
-   usb_put_intf(dev-intf);
-   usb_put_dev(dev-udev);
-
uvc_status_cleanup(dev);
uvc_ctrl_cleanup_device(dev);
 
+   usb_put_intf(dev-intf);
+   usb_put_dev(dev-udev);
+
if (dev-vdev.dev)
v4l2_device_unregister(dev-vdev);
 #ifdef CONFIG_MEDIA_CONTROLLER
-- 
2.1.2

--
To unsubscribe from this list: send the line unsubscribe linux-media in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH v2 1/6] media: add media token device resource framework

2014-10-21 Thread Takashi Iwai
At Tue, 21 Oct 2014 12:46:03 +0200,
Hans Verkuil wrote:
 
 Hi Shuah,
 
 As promised, here is my review for this patch series.
 
 On 10/14/2014 04:58 PM, Shuah Khan wrote:
  Add media token device resource framework to allow sharing
  resources such as tuner, dma, audio etc. across media drivers
  and non-media sound drivers that control media hardware. The
  Media token resource is created at the main struct device that
  is common to all drivers that claim various pieces of the main
  media device, which allows them to find the resource using the
  main struct device. As an example, digital, analog, and
  snd-usb-audio drivers can use the media token resource API
  using the main struct device for the interface the media device
  is attached to.
 
  A shared media tokens resource is created using devres framework
  for drivers to find and lock/unlock. Creating a shared devres
  helps avoid creating data structure dependencies between drivers.
  This media token resource contains media token for tuner, and
  audio. When tuner token is requested, audio token is issued.
 
 Did you mean: 'tuner token is issued' instead of audio token?
 
 I also have the same question as Takashi: why do we have an audio
 token in the first place? While you are streaming audio over alsa
 the underlying tuner must be marked as being in use. It's all about
 the tuner, since that's the resource that is being shared, not about
 audio as such.
 
 For the remainder of my review I will ignore the audio-related code
 and concentrate only on the tuner part.
 
  Subsequent token (for tuner and audio) gets from the same task
  and task in the same tgid succeed. This allows applications that
  make multiple v4l2 ioctls to work with the first call acquiring
  the token and applications that create separate threads to handle
  video and audio functions.
 
  Signed-off-by: Shuah Khan shua...@osg.samsung.com
  ---
MAINTAINERS  |2 +
include/linux/media_tknres.h |   50 +
lib/Makefile |2 +
lib/media_tknres.c   |  237 
  ++
 
 I am still not convinced myself that this should be a generic API.
 The only reason we need it today is for sharing tuners. Which is almost
 a purely media thing with USB audio as the single non-media driver that
 will be affected. Today I see no use case outside of tuners. I would
 probably want to keep this inside drivers/media.
 
 If this is going to be expanded it can always be moved to lib later.

Well, my argument is that it should be more generic if it were
intended to be put in lib.  It'd be fine to put into drivers/media,
but this code snippet must be a separate module.  Otherwise usb-audio
would grab the whole media stuff even if not needed at all.

(snip)
 I also discovered that you are missing MODULE_AUTHOR, MODULE_DESCRIPTION
 and above all MODULE_LICENSE. Without the MODULE_LICENSE it won't link this
 module to the GPL devres_* functions. It took me some time to figure that
 out.

It was a code in lib, so it cannot be a module at all :)


Takashi
--
To unsubscribe from this list: send the line unsubscribe linux-media in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH v2 1/6] media: add media token device resource framework

2014-10-21 Thread Takashi Iwai
At Tue, 21 Oct 2014 13:58:59 +0200,
Hans Verkuil wrote:
 
 
 
 On 10/21/2014 01:51 PM, Takashi Iwai wrote:
  At Tue, 21 Oct 2014 12:46:03 +0200,
  Hans Verkuil wrote:
 
  Hi Shuah,
 
  As promised, here is my review for this patch series.
 
  On 10/14/2014 04:58 PM, Shuah Khan wrote:
  Add media token device resource framework to allow sharing
  resources such as tuner, dma, audio etc. across media drivers
  and non-media sound drivers that control media hardware. The
  Media token resource is created at the main struct device that
  is common to all drivers that claim various pieces of the main
  media device, which allows them to find the resource using the
  main struct device. As an example, digital, analog, and
  snd-usb-audio drivers can use the media token resource API
  using the main struct device for the interface the media device
  is attached to.
 
  A shared media tokens resource is created using devres framework
  for drivers to find and lock/unlock. Creating a shared devres
  helps avoid creating data structure dependencies between drivers.
  This media token resource contains media token for tuner, and
  audio. When tuner token is requested, audio token is issued.
 
  Did you mean: 'tuner token is issued' instead of audio token?
 
  I also have the same question as Takashi: why do we have an audio
  token in the first place? While you are streaming audio over alsa
  the underlying tuner must be marked as being in use. It's all about
  the tuner, since that's the resource that is being shared, not about
  audio as such.
 
  For the remainder of my review I will ignore the audio-related code
  and concentrate only on the tuner part.
 
  Subsequent token (for tuner and audio) gets from the same task
  and task in the same tgid succeed. This allows applications that
  make multiple v4l2 ioctls to work with the first call acquiring
  the token and applications that create separate threads to handle
  video and audio functions.
 
  Signed-off-by: Shuah Khan shua...@osg.samsung.com
  ---
 MAINTAINERS  |2 +
 include/linux/media_tknres.h |   50 +
 lib/Makefile |2 +
 lib/media_tknres.c   |  237 
  ++
 
  I am still not convinced myself that this should be a generic API.
  The only reason we need it today is for sharing tuners. Which is almost
  a purely media thing with USB audio as the single non-media driver that
  will be affected. Today I see no use case outside of tuners. I would
  probably want to keep this inside drivers/media.
 
  If this is going to be expanded it can always be moved to lib later.
 
  Well, my argument is that it should be more generic if it were
  intended to be put in lib.  It'd be fine to put into drivers/media,
  but this code snippet must be a separate module.  Otherwise usb-audio
  would grab the whole media stuff even if not needed at all.
 
 Certainly.
 
 
  (snip)
  I also discovered that you are missing MODULE_AUTHOR, MODULE_DESCRIPTION
  and above all MODULE_LICENSE. Without the MODULE_LICENSE it won't link this
  module to the GPL devres_* functions. It took me some time to figure that
  out.
 
  It was a code in lib, so it cannot be a module at all :)
 
 Well, it depends on CONFIG_MEDIA_SUPPORT which is 'm' in my case, so it
 compiles as a module :-)

Ah, I thought it was a boolean, but yes, this can be a module indeed.
Then I don't think it's worth to put in lib.


Takashi
--
To unsubscribe from this list: send the line unsubscribe linux-media in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [alsa-devel] [PATCH v2 5/6] sound/usb: pcm changes to use media token api

2014-10-21 Thread Takashi Iwai
At Tue, 21 Oct 2014 17:42:51 +0200,
Hans Verkuil wrote:
 
 
 
 On 10/16/2014 04:48 PM, Takashi Iwai wrote:
  At Thu, 16 Oct 2014 08:39:14 -0600,
  Shuah Khan wrote:
 
  On 10/16/2014 08:16 AM, Takashi Iwai wrote:
  At Thu, 16 Oct 2014 08:10:52 -0600,
  Shuah Khan wrote:
 
  On 10/16/2014 08:01 AM, Takashi Iwai wrote:
  At Thu, 16 Oct 2014 07:10:37 -0600,
  Shuah Khan wrote:
 
  On 10/16/2014 06:00 AM, Lars-Peter Clausen wrote:
  On 10/14/2014 04:58 PM, Shuah Khan wrote:
  [...]
 switch (cmd) {
 case SNDRV_PCM_TRIGGER_START:
  +err = media_get_audio_tkn(subs-dev-dev);
  +if (err == -EBUSY) {
  +dev_info(subs-dev-dev, %s device is busy\n,
  +__func__);
 
  In my opinion this should not dev_info() as this is out of band error
  signaling and also as the potential to spam the log. The userspace
  application is already properly notified by the return code.
 
 
  Yes it has the potential to flood the dmesg especially with alsa,
  I will remove the dev_info().
 
  Yes.  And, I think doing this in the trigger isn't the best.
  Why not in open  close?
 
  My first cut of this change was in open and close. I saw pulseaudio
  application go into this loop trying to open the device. To avoid
  such problems, I went with trigger stat and stop. That made all the
  pulseaudio continues attempts to open problems go away.
 
  But now starting the stream gives the error, and PA would loop it
  again, no?
 
 
  Also, is this token restriction needed only for PCM?  No mixer or
  other controls?
 
  snd_pcm_ops are the only ones media drivers implement and use. So
  I don't think mixer is needed. If it is needed, it is not to hard
  to add for that case.
 
  Well, then I wonder what resource does actually conflict with
  usb-audio and media drivers at all...?
 
 
  audio for dvb/v4l apps gets disrupted when audio app starts. For
  example, dvb or v4l app tuned to a channel, and when an audio app
  starts. audio path needs protected to avoid conflicts between
  digital and analog applications as well.
 
  OK, then concentrating on only PCM is fine.
 
  But, I'm still not convinced about doing the token management in the
  trigger.  The reason -EBUSY doesn't work is that it's the very same
  error code when a PCM device is blocked by other processes.  And
  -EAGAIN is interpreted by PCM core to -EBUSY for historical reasons.
 
  How applications (e.g. PA) should behave if the token get fails?
  Shouldn't it retry or totally give up?
 
 Quite often media apps open the alsa device at the start and then switch
 between TV, radio or DVB mode. If the alsa device would claim the tuner
 just by being opened (as opposed to actually using the tuner, which happens
 when you start streaming),

What about parameter changes?  The sound devices have to be configured
before using.  Don't they influence on others at all, i.e. you can
change the PCM sample rate etc during TV, radio or DVB is running?

 then that would make it impossible for the
 application to switch tuner mode. In general you want to avoid that open()
 will start configuring hardware since that can quite often be slow. Tuner
 configuration in particular can be slow since several common tuners need
 to load firmware over i2c. You only want to do that when it is really needed,
 and not when some application (udev!) opens the device just to examine what
 sort of device it is.

But most apps close the device soon after that, no?
Which programs keep the PCM device (not the control) opened without
actually using?

 So claiming the tuner in the trigger seems to be the right place. If
 returning EBUSY is a poor error code for alsa, then we can use something else
 for that. EACCES perhaps?

Sorry, I'm not convinced by that.  If the device has to be controlled
exclusively, the right position is the open/close.  Otherwise, the
program cannot know when it becomes inaccessible out of sudden during
its operation.


Takashi
--
To unsubscribe from this list: send the line unsubscribe linux-media in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [alsa-devel] [PATCH v2 5/6] sound/usb: pcm changes to use media token api

2014-10-21 Thread Takashi Iwai
At Tue, 21 Oct 2014 12:08:59 -0400,
Devin Heitmueller wrote:
 
  Sorry, I'm not convinced by that.  If the device has to be controlled
  exclusively, the right position is the open/close.  Otherwise, the
  program cannot know when it becomes inaccessible out of sudden during
  its operation.
 
 I can say that I've definitely seen cases where if you configure a
 device as the default capture device in PulseAudio, then pulse will
 continue to capture from it even if you're not actively capturing the
 audio from pulse.  I only spotted this because I had a USB analyzer on
 the device and was dumbfounded when the ISOC packets kept arriving
 even after I had closed VLC.

You might have had an input monitor active in some PA apps?
PA shouldn't do it as default.  If it does unintentionally, you should
report it to PA guys.


Takashi
--
To unsubscribe from this list: send the line unsubscribe linux-media in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH] DocBook: Reduce noise from make cleandocs

2014-10-21 Thread Takashi Iwai
I've got a harmless warning when running make cleandocs on an already
cleaned tree:
  Documentation/DocBook/media/Makefile:28: recipe for target 'cleanmediadocs' 
failed
  make[1]: [cleanmediadocs] Error 1 (ignored)

Suppress this by passing -f to rm.

Signed-off-by: Takashi Iwai ti...@suse.de
---
 Documentation/DocBook/media/Makefile | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/Documentation/DocBook/media/Makefile 
b/Documentation/DocBook/media/Makefile
index df2962d9e11e..8bf7c6191296 100644
--- a/Documentation/DocBook/media/Makefile
+++ b/Documentation/DocBook/media/Makefile
@@ -25,7 +25,7 @@ GENFILES := $(addprefix $(MEDIA_OBJ_DIR)/, $(MEDIA_TEMP))
 PHONY += cleanmediadocs
 
 cleanmediadocs:
-   -@rm `find $(MEDIA_OBJ_DIR) -type l` $(GENFILES) $(OBJIMGFILES) 
2/dev/null
+   -@rm -f `find $(MEDIA_OBJ_DIR) -type l` $(GENFILES) $(OBJIMGFILES) 
2/dev/null
 
 $(obj)/media_api.xml: $(GENFILES) FORCE
 
-- 
2.1.2

--
To unsubscribe from this list: send the line unsubscribe linux-media in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [alsa-devel] [PATCH v2 5/6] sound/usb: pcm changes to use media token api

2014-10-19 Thread Takashi Iwai
At Sat, 18 Oct 2014 20:49:58 +0200,
Mauro Carvalho Chehab wrote:
 
 Em Thu, 16 Oct 2014 08:59:29 -0600
 Shuah Khan shua...@osg.samsung.com escreveu:
 
  On 10/16/2014 08:48 AM, Takashi Iwai wrote:
   At Thu, 16 Oct 2014 08:39:14 -0600,
   Shuah Khan wrote:
  
   On 10/16/2014 08:16 AM, Takashi Iwai wrote:
   At Thu, 16 Oct 2014 08:10:52 -0600,
   Shuah Khan wrote:
  
   On 10/16/2014 08:01 AM, Takashi Iwai wrote:
   At Thu, 16 Oct 2014 07:10:37 -0600,
   Shuah Khan wrote:
  
   On 10/16/2014 06:00 AM, Lars-Peter Clausen wrote:
   On 10/14/2014 04:58 PM, Shuah Khan wrote:
   [...]
 switch (cmd) {
 case SNDRV_PCM_TRIGGER_START:
   +err = media_get_audio_tkn(subs-dev-dev);
   +if (err == -EBUSY) {
   +dev_info(subs-dev-dev, %s device is busy\n,
   +__func__);
  
   In my opinion this should not dev_info() as this is out of band 
   error
   signaling and also as the potential to spam the log. The userspace
   application is already properly notified by the return code.
  
  
   Yes it has the potential to flood the dmesg especially with alsa,
   I will remove the dev_info().
  
   Yes.  And, I think doing this in the trigger isn't the best.
   Why not in open  close?
  
   My first cut of this change was in open and close. I saw pulseaudio
   application go into this loop trying to open the device. To avoid
   such problems, I went with trigger stat and stop. That made all the
   pulseaudio continues attempts to open problems go away.
  
   But now starting the stream gives the error, and PA would loop it
   again, no?
  
  
   Also, is this token restriction needed only for PCM?  No mixer or
   other controls?
  
   snd_pcm_ops are the only ones media drivers implement and use. So
   I don't think mixer is needed. If it is needed, it is not to hard
   to add for that case.
  
   Well, then I wonder what resource does actually conflict with
   usb-audio and media drivers at all...?
  
  
   audio for dvb/v4l apps gets disrupted when audio app starts. For
   example, dvb or v4l app tuned to a channel, and when an audio app
   starts. audio path needs protected to avoid conflicts between
   digital and analog applications as well.
   
   OK, then concentrating on only PCM is fine.
   
   But, I'm still not convinced about doing the token management in the
   trigger.  The reason -EBUSY doesn't work is that it's the very same
   error code when a PCM device is blocked by other processes.  And
   -EAGAIN is interpreted by PCM core to -EBUSY for historical reasons.
  
  ah. ok your recommendation is to go with open and close.
  Mauro has some reservations with holding at open when I discussed
  my observations with pulseaudio when I was holding token in open
  instead of trigger start. Maybe he can chime with his concerns.
  I think his concern was breaking applications if token is held in
  open().
 
 Yes. My concern is that PA has weird behaviors, and it tries to open and
 keep opened all audio devices.

PA usually closes the PCM devices when unused.  If it doesn't, it must
be a bug.


Takashi
--
To unsubscribe from this list: send the line unsubscribe linux-media in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH v2 1/6] media: add media token device resource framework

2014-10-16 Thread Takashi Iwai
At Wed, 15 Oct 2014 18:53:28 -0600,
Shuah Khan wrote:
 
 On 10/15/2014 11:05 AM, Takashi Iwai wrote:
 
  +#if defined(CONFIG_MEDIA_SUPPORT)
  +extern int media_tknres_create(struct device *dev);
  +extern int media_tknres_destroy(struct device *dev);
  +
  +extern int media_get_tuner_tkn(struct device *dev);
  +extern int media_put_tuner_tkn(struct device *dev);
  +
  +extern int media_get_audio_tkn(struct device *dev);
  +extern int media_put_audio_tkn(struct device *dev);
  
  The words tknres and tkn (especially latter) look ugly and not
  clear to me.  IMO, it should be token.
 
 No problem. I can change that to media_token_create/destroy()
 and expand token in other functions.
 
  +struct media_tkn {
  +  spinlock_t lock;
  +  unsigned int owner; /* owner task pid */
  +  unsigned int tgid;  /* owner task gid */
  +  struct task_struct *task;
  +};
  +
  +struct media_tknres {
  +  struct media_tkn tuner;
  +  struct media_tkn audio;
  +};
  
  Why do you need to have both tuner and audio tokens?  If I understand
  correctly, no matter whether it's tuner or audio, if it's being used,
  the open must fail, right?
 
 As it evolved during development, it turns out at the moment I don't
 have any use-cases that require holding audio and tuner separately.
 It probably could be collapsed into just a media token. I have to
 think about this some.
 
  +
  +static int __media_get_tkn(struct media_tkn *tkn, char *tkn_str)
  +{
  +  int rc = 0;
  +  unsigned tpid;
  +  unsigned tgid;
  +
  +  spin_lock(tkn-lock);
  
  You should use spin_lock_irqsave() here and in all other places.
  The trigger callback in usb-audio, for example, may be called in irq
  context.
 
 ok. Good point, will change that.
 
  
  +
  +  tpid = task_pid_nr(current);
  +  tgid = task_tgid_nr(current);
  +
  +  /* allow task in the same group id to release */
  
  IMO, it's not release but steal...  But what happens if the stolen
  owner calls put?  Then it'll be released although the stealing owner
  still thinks it's being held.
 
 Yeah it could be called a steal. :) Essentially tgid happens to be
 the real owner. I am overwriting the pid with current pid when
 tgid is same.
 
 media dvb and v4l apps start two or more threads that all share the
 tgid and subsequent token gets should be allowed based on the tgid.
 
 Scenario 1:
 
 Please note that there are 3 device files in question and media
 token resource is the lock for all. Hence the changes to v4l-core,
 dvb-core, and snd-usb-audio to hold the token for exclusive access
 when the task or tgid don't match.
 
 program starts:
 - first thread opens device file in R/W mode - open gets the token
   or thread makes ioctls calls that clearly indicates intent to
   change tuner settings
 - creates one thread for audio
 - creates another for video or continues video function
 - video thread does a close and re-opens the device file
 
   In this case when thread tries to close, token put fails unless
   tasks with same tgid are allowed to release.
   ( I ran into this one of the media applications and it is a valid
 case to handle, thread can close the file and should be able to
 open again without running into token busy case )
 
 - or continue to just use the device file
 - audio thread does snd_pcm_capture ops - trigger start
 
 program exits:
 - video thread closes the device file
 - audio thread does snd_pcm_capture ops - trigger stop
 
 This got me thinking about the scenario when an application
 does a fork() as opposed to create a thread. I have to think
 about this and see how I can address that.
 
  
  +  if (tkn-task  ((tkn-task != current)  (tkn-tgid != tgid))) {
  
  Shouldn't the second  be || instead?
  And too many parentheses there.
 
 Right - this is my bad. The comment right above this conditional
 is a give away that, at some point I did a copy and paste from
 _put to _get and only changed the first task null check.
 I am yelling at myself at the moment.
 
  
  +  rc = -EBUSY;
  
  Wrong indentation.
 
 Yes. Will fix that.
 
  
  I have a feeling that the whole thing can be a bit more simplified in
  the end...
  
 
 Any ideas to simplify are welcome.

There are a few points to make things more consistent and simplified,
IMO.  First of all, the whole concept can be more generalized.  It's
not necessarily only for media and audio.  Rather we can make it a
generic dev_token.  Then it'll become more convincing to land into
lib/*.

The media-specific handling is only about the pid and gid checks.
This can be implemented as a callback that is passed at creating a
token, for example.  This will reduce the core code in lib/*.

Also, get and put should handle a proper refcount.  The point I
mentioned in my previous post is the possible unbalance, and you'll
see unexpected unlock in the scenario.  In addition, with use of kref,
the lock can be removed.

So, essentially the lib code would be just a devres_alloc() for an
object with kref

Re: [alsa-devel] [PATCH v2 5/6] sound/usb: pcm changes to use media token api

2014-10-16 Thread Takashi Iwai
At Thu, 16 Oct 2014 07:10:37 -0600,
Shuah Khan wrote:
 
 On 10/16/2014 06:00 AM, Lars-Peter Clausen wrote:
  On 10/14/2014 04:58 PM, Shuah Khan wrote:
  [...]
switch (cmd) {
case SNDRV_PCM_TRIGGER_START:
  +err = media_get_audio_tkn(subs-dev-dev);
  +if (err == -EBUSY) {
  +dev_info(subs-dev-dev, %s device is busy\n,
  +__func__);
  
  In my opinion this should not dev_info() as this is out of band error
  signaling and also as the potential to spam the log. The userspace
  application is already properly notified by the return code.
  
 
 Yes it has the potential to flood the dmesg especially with alsa,
 I will remove the dev_info().

Yes.  And, I think doing this in the trigger isn't the best.
Why not in open  close?

Also, is this token restriction needed only for PCM?  No mixer or
other controls?


Takashi
--
To unsubscribe from this list: send the line unsubscribe linux-media in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH v2 0/6] media token resource framework

2014-10-16 Thread Takashi Iwai
At Wed, 15 Oct 2014 14:21:34 -0600,
Shuah Khan wrote:
 
 On 10/15/2014 10:48 AM, Takashi Iwai wrote:
  At Tue, 14 Oct 2014 08:58:36 -0600,
  Shuah Khan wrote:
 
  Add media token device resource framework to allow sharing
  resources such as tuner, dma, audio etc. across media drivers
  and non-media sound drivers that control media hardware. The
  Media token resource is created at the main struct device that
  is common to all drivers that claim various pieces of the main
  media device, which allows them to find the resource using the
  main struct device. As an example, digital, analog, and
  snd-usb-audio drivers can use the media token resource API
  using the main struct device for the interface the media device
  is attached to.
 
  This patch series consists of media token resource framework
  and changes to use it in dvb-core, v4l2-core, au0828 driver,
  and snd-usb-audio driver.
 
  With these changes dvb and v4l2 can share the tuner without
  disrupting each other. Used tvtime, xawtv, kaffeine, and vlc,
  vlc audio capture option, arecord/aplay during development to
  identify v4l2 vb2 and vb1 ioctls and file operations that
  disrupt the digital stream and would require changes to check
  tuner ownership prior to changing the tuner configuration.
  vb2 changes are made in the v4l2-core and vb1 changes are made
  in the au0828 driver to encourage porting drivers to vb2 to
  advantage of the new media token resource framework with changes
  in the core.
 
  In this patch v2 series, fixed problems identified in the
  patch v1 series. Important ones are changing snd-usb-audio
  to use media tokens, holding tuner lock in VIDIOC_ENUMINPUT,
  and VIDIOC_QUERYSTD.
  
  Just took a quick glance over the patches, and my first concern is why
  this has to be lib/*.  This means it's always built-in as long as this
  config is enabled (and will be so on distro kernel) even if it's not
  used at all.
  
 
 Right this module gets built when CONFIG_MEDIA_SUPPORT is enabled
 and stubs are in place when it is not enabled. The intent is for
 this feature to be enabled by default when media support is enabled.
 When a driver doesn't create the resource, it will simply not find it
 and for drivers like snd-usb-audio that aren't tried to media support,
 the stubs are in place and feature is essentially disabled.
 
 I picked lib so this module can be included in non-media drivers
 e.g: snd-usb-audio.
 
 Does this help explain the design? I didn't want to introduce a new
 config for this feature. If lib isn't right place, could you recommend
 another one that makes this modules available to non-media drivers?
 moving isn't a problem.

We can create a small module depending on CONFIG_MEDIA.  But it'll be
rather a question of the size.  If it's reasonably small and generic
enough, it's worth to put into lib/*, I think.


Takashi
--
To unsubscribe from this list: send the line unsubscribe linux-media in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [alsa-devel] [PATCH v2 5/6] sound/usb: pcm changes to use media token api

2014-10-16 Thread Takashi Iwai
At Thu, 16 Oct 2014 08:10:52 -0600,
Shuah Khan wrote:
 
 On 10/16/2014 08:01 AM, Takashi Iwai wrote:
  At Thu, 16 Oct 2014 07:10:37 -0600,
  Shuah Khan wrote:
 
  On 10/16/2014 06:00 AM, Lars-Peter Clausen wrote:
  On 10/14/2014 04:58 PM, Shuah Khan wrote:
  [...]
switch (cmd) {
case SNDRV_PCM_TRIGGER_START:
  +err = media_get_audio_tkn(subs-dev-dev);
  +if (err == -EBUSY) {
  +dev_info(subs-dev-dev, %s device is busy\n,
  +__func__);
 
  In my opinion this should not dev_info() as this is out of band error
  signaling and also as the potential to spam the log. The userspace
  application is already properly notified by the return code.
 
 
  Yes it has the potential to flood the dmesg especially with alsa,
  I will remove the dev_info().
  
  Yes.  And, I think doing this in the trigger isn't the best.
  Why not in open  close?
 
 My first cut of this change was in open and close. I saw pulseaudio
 application go into this loop trying to open the device. To avoid
 such problems, I went with trigger stat and stop. That made all the
 pulseaudio continues attempts to open problems go away.

But now starting the stream gives the error, and PA would loop it
again, no?


  Also, is this token restriction needed only for PCM?  No mixer or
  other controls?
 
 snd_pcm_ops are the only ones media drivers implement and use. So
 I don't think mixer is needed. If it is needed, it is not to hard
 to add for that case.

Well, then I wonder what resource does actually conflict with
usb-audio and media drivers at all...?


Takashi
--
To unsubscribe from this list: send the line unsubscribe linux-media in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [alsa-devel] [PATCH v2 5/6] sound/usb: pcm changes to use media token api

2014-10-16 Thread Takashi Iwai
At Thu, 16 Oct 2014 08:39:14 -0600,
Shuah Khan wrote:
 
 On 10/16/2014 08:16 AM, Takashi Iwai wrote:
  At Thu, 16 Oct 2014 08:10:52 -0600,
  Shuah Khan wrote:
 
  On 10/16/2014 08:01 AM, Takashi Iwai wrote:
  At Thu, 16 Oct 2014 07:10:37 -0600,
  Shuah Khan wrote:
 
  On 10/16/2014 06:00 AM, Lars-Peter Clausen wrote:
  On 10/14/2014 04:58 PM, Shuah Khan wrote:
  [...]
switch (cmd) {
case SNDRV_PCM_TRIGGER_START:
  +err = media_get_audio_tkn(subs-dev-dev);
  +if (err == -EBUSY) {
  +dev_info(subs-dev-dev, %s device is busy\n,
  +__func__);
 
  In my opinion this should not dev_info() as this is out of band error
  signaling and also as the potential to spam the log. The userspace
  application is already properly notified by the return code.
 
 
  Yes it has the potential to flood the dmesg especially with alsa,
  I will remove the dev_info().
 
  Yes.  And, I think doing this in the trigger isn't the best.
  Why not in open  close?
 
  My first cut of this change was in open and close. I saw pulseaudio
  application go into this loop trying to open the device. To avoid
  such problems, I went with trigger stat and stop. That made all the
  pulseaudio continues attempts to open problems go away.
  
  But now starting the stream gives the error, and PA would loop it
  again, no?
  
  
  Also, is this token restriction needed only for PCM?  No mixer or
  other controls?
 
  snd_pcm_ops are the only ones media drivers implement and use. So
  I don't think mixer is needed. If it is needed, it is not to hard
  to add for that case.
  
  Well, then I wonder what resource does actually conflict with
  usb-audio and media drivers at all...?
  
 
 audio for dvb/v4l apps gets disrupted when audio app starts. For
 example, dvb or v4l app tuned to a channel, and when an audio app
 starts. audio path needs protected to avoid conflicts between
 digital and analog applications as well.

OK, then concentrating on only PCM is fine.

But, I'm still not convinced about doing the token management in the
trigger.  The reason -EBUSY doesn't work is that it's the very same
error code when a PCM device is blocked by other processes.  And
-EAGAIN is interpreted by PCM core to -EBUSY for historical reasons.

How applications (e.g. PA) should behave if the token get fails?
Shouldn't it retry or totally give up?


Takashi
--
To unsubscribe from this list: send the line unsubscribe linux-media in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH v2 0/6] media token resource framework

2014-10-15 Thread Takashi Iwai
At Tue, 14 Oct 2014 08:58:36 -0600,
Shuah Khan wrote:
 
 Add media token device resource framework to allow sharing
 resources such as tuner, dma, audio etc. across media drivers
 and non-media sound drivers that control media hardware. The
 Media token resource is created at the main struct device that
 is common to all drivers that claim various pieces of the main
 media device, which allows them to find the resource using the
 main struct device. As an example, digital, analog, and
 snd-usb-audio drivers can use the media token resource API
 using the main struct device for the interface the media device
 is attached to.
 
 This patch series consists of media token resource framework
 and changes to use it in dvb-core, v4l2-core, au0828 driver,
 and snd-usb-audio driver.
 
 With these changes dvb and v4l2 can share the tuner without
 disrupting each other. Used tvtime, xawtv, kaffeine, and vlc,
 vlc audio capture option, arecord/aplay during development to
 identify v4l2 vb2 and vb1 ioctls and file operations that
 disrupt the digital stream and would require changes to check
 tuner ownership prior to changing the tuner configuration.
 vb2 changes are made in the v4l2-core and vb1 changes are made
 in the au0828 driver to encourage porting drivers to vb2 to
 advantage of the new media token resource framework with changes
 in the core.
 
 In this patch v2 series, fixed problems identified in the
 patch v1 series. Important ones are changing snd-usb-audio
 to use media tokens, holding tuner lock in VIDIOC_ENUMINPUT,
 and VIDIOC_QUERYSTD.

Just took a quick glance over the patches, and my first concern is why
this has to be lib/*.  This means it's always built-in as long as this
config is enabled (and will be so on distro kernel) even if it's not
used at all.


thanks,

Takashi
--
To unsubscribe from this list: send the line unsubscribe linux-media in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH v2 1/6] media: add media token device resource framework

2014-10-15 Thread Takashi Iwai
At Tue, 14 Oct 2014 08:58:37 -0600,
Shuah Khan wrote:
 
 Add media token device resource framework to allow sharing
 resources such as tuner, dma, audio etc. across media drivers
 and non-media sound drivers that control media hardware. The
 Media token resource is created at the main struct device that
 is common to all drivers that claim various pieces of the main
 media device, which allows them to find the resource using the
 main struct device. As an example, digital, analog, and
 snd-usb-audio drivers can use the media token resource API
 using the main struct device for the interface the media device
 is attached to.
 
 A shared media tokens resource is created using devres framework
 for drivers to find and lock/unlock. Creating a shared devres
 helps avoid creating data structure dependencies between drivers.
 This media token resource contains media token for tuner, and
 audio. When tuner token is requested, audio token is issued.
 Subsequent token (for tuner and audio) gets from the same task
 and task in the same tgid succeed. This allows applications that
 make multiple v4l2 ioctls to work with the first call acquiring
 the token and applications that create separate threads to handle
 video and audio functions.
 
 Signed-off-by: Shuah Khan shua...@osg.samsung.com
 ---
  MAINTAINERS  |2 +
  include/linux/media_tknres.h |   50 +
  lib/Makefile |2 +
  lib/media_tknres.c   |  237 
 ++
  4 files changed, 291 insertions(+)
  create mode 100644 include/linux/media_tknres.h
  create mode 100644 lib/media_tknres.c
 
 diff --git a/MAINTAINERS b/MAINTAINERS
 index e80a275..9216179 100644
 --- a/MAINTAINERS
 +++ b/MAINTAINERS
 @@ -5864,6 +5864,8 @@ F:  include/uapi/linux/v4l2-*
  F:   include/uapi/linux/meye.h
  F:   include/uapi/linux/ivtv*
  F:   include/uapi/linux/uvcvideo.h
 +F:   include/linux/media_tknres.h
 +F:   lib/media_tknres.c
  
  MEDIAVISION PRO MOVIE STUDIO DRIVER
  M:   Hans Verkuil hverk...@xs4all.nl
 diff --git a/include/linux/media_tknres.h b/include/linux/media_tknres.h
 new file mode 100644
 index 000..6d37327
 --- /dev/null
 +++ b/include/linux/media_tknres.h
 @@ -0,0 +1,50 @@
 +/*
 + * media_tknres.h - managed media token resource
 + *
 + * Copyright (c) 2014 Shuah Khan shua...@osg.samsung.com
 + * Copyright (c) 2014 Samsung Electronics Co., Ltd.
 + *
 + * This file is released under the GPLv2.
 + */
 +#ifndef __LINUX_MEDIA_TOKEN_H
 +#define __LINUX_MEDIA_TOKEN_H
 +
 +struct device;
 +
 +#if defined(CONFIG_MEDIA_SUPPORT)
 +extern int media_tknres_create(struct device *dev);
 +extern int media_tknres_destroy(struct device *dev);
 +
 +extern int media_get_tuner_tkn(struct device *dev);
 +extern int media_put_tuner_tkn(struct device *dev);
 +
 +extern int media_get_audio_tkn(struct device *dev);
 +extern int media_put_audio_tkn(struct device *dev);

The words tknres and tkn (especially latter) look ugly and not
clear to me.  IMO, it should be token.

 +#else
 +static inline int media_tknres_create(struct device *dev)
 +{
 + return 0;
 +}
 +static inline int media_tknres_destroy(struct device *dev)
 +{
 + return 0;
 +}
 +static inline int media_get_tuner_tkn(struct device *dev)
 +{
 + return 0;
 +}
 +static inline int media_put_tuner_tkn(struct device *dev)
 +{
 + return 0;
 +}
 +static int media_get_audio_tkn(struct device *dev)
 +{
 + return 0;
 +}
 +static int media_put_audio_tkn(struct device *dev)
 +{
 + return 0;
 +}
 +#endif
 +
 +#endif   /* __LINUX_MEDIA_TOKEN_H */
 diff --git a/lib/Makefile b/lib/Makefile
 index d6b4bc4..6f21695 100644
 --- a/lib/Makefile
 +++ b/lib/Makefile
 @@ -139,6 +139,8 @@ obj-$(CONFIG_DQL) += dynamic_queue_limits.o
  
  obj-$(CONFIG_GLOB) += glob.o
  
 +obj-$(CONFIG_MEDIA_SUPPORT) += media_tknres.o
 +
  obj-$(CONFIG_MPILIB) += mpi/
  obj-$(CONFIG_SIGNATURE) += digsig.o
  
 diff --git a/lib/media_tknres.c b/lib/media_tknres.c
 new file mode 100644
 index 000..e0a36cb
 --- /dev/null
 +++ b/lib/media_tknres.c
 @@ -0,0 +1,237 @@
 +/*
 + * media_tknres.c - managed media token resource
 + *
 + * Copyright (c) 2014 Shuah Khan shua...@osg.samsung.com
 + * Copyright (c) 2014 Samsung Electronics Co., Ltd.
 + *
 + * This file is released under the GPLv2.
 + */
 +/*
 + * Media devices often have hardware resources that are shared
 + * across several functions. For instance, TV tuner cards often
 + * have MUXes, converters, radios, tuners, etc. that are shared
 + * across various functions. However, v4l2, alsa, DVB, usbfs, and
 + * all other drivers have no knowledge of what resources are
 + * shared. For example, users can't access DVB and alsa at the same
 + * time, or the DVB and V4L analog API at the same time, since many
 + * only have one converter that can be in either analog or digital
 + * mode. Accessing and/or changing mode of a converter while it is
 + * in use by another function results in video stream error.
 + *
 + 

[ANNOUNCE] Linux Audio Mini Summit 2014, Oct. 14, Düsseldorf, Germany

2014-09-05 Thread Takashi Iwai
Hi,

like previous years, we're going to hold a meeting to discuss
lowlevel audio on Linux.  This time it's along with Linux Plumbers
conference, but for avoiding the conflicts with other LPC mini
conferences (including Media Mini-summit, of course :), it'll be held
on Tuesday October 14, at the same venue as LPC, Congress Center
Düsseldorf, Germany.

If anyone is interested, feel free to sign up in the attendee list
below.  It's a public accessible Google doc, so you can edit freely.

http://goo.gl/VbXLPW

(or 
https://docs.google.com/spreadsheets/d/1wBAiAyZSnMjVFJbxdXE5JoVdKGIBIWt-4tuSsHzGw4w/edit?usp=sharing)

The topics that have been currently raised are found in the URL below.
If you have any more topics to discuss there, just put your favorite
one in the URL below as well.

http://goo.gl/JSasQ9

(or 
https://docs.google.com/spreadsheets/d/1cXzON65QYNrTXi31AIQHffUZ9NWwJuNEJAC0ubfKlZc/edit?usp=sharing)

If you have any question or suggestion, drop me a mail.


Thanks!

Takashi
--
To unsubscribe from this list: send the line unsubscribe linux-media in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH] [media] ivtv: Fix Oops when no firmware is loaded

2014-05-05 Thread Takashi Iwai
When ivtv PCM device is accessed at the state where no firmware is
loaded, it oopses like:

  BUG: unable to handle kernel NULL pointer dereference at 0050
  IP: [a049a881] try_mailbox.isra.0+0x11/0x50 [ivtv]
  Call Trace:
[a049aa20] ivtv_api_call+0x160/0x6b0 [ivtv]
[a049af86] ivtv_api+0x16/0x40 [ivtv]
[a049b10c] ivtv_vapi+0xac/0xc0 [ivtv]
[a049d40d] ivtv_start_v4l2_encode_stream+0x19d/0x630 [ivtv]
[a0530653] snd_ivtv_pcm_capture_open+0x173/0x1c0 [ivtv_alsa]
[a04526f1] snd_pcm_open_substream+0x51/0x100 [snd_pcm]
[a0452853] snd_pcm_open+0xb3/0x260 [snd_pcm]
[a0452a37] snd_pcm_capture_open+0x37/0x50 [snd_pcm]
[a033f557] snd_open+0xa7/0x1e0 [snd]
[8118a628] chrdev_open+0x88/0x1d0
[811840be] do_dentry_open+0x1de/0x270
[81193a73] do_last+0x1c3/0xec0
[81194826] path_openat+0xb6/0x670
[81195b65] do_filp_open+0x35/0x80
[81185449] do_sys_open+0x129/0x210
[815b782d] system_call_fastpath+0x1a/0x1f

This patch adds the check of firmware at PCM open callback like other
open callbacks of this driver.

Bugzilla: https://apibugzilla.novell.com/show_bug.cgi?id=875440
Cc: sta...@vger.kernel.org
Signed-off-by: Takashi Iwai ti...@suse.de
---
 drivers/media/pci/ivtv/ivtv-alsa-pcm.c | 6 ++
 1 file changed, 6 insertions(+)

diff --git a/drivers/media/pci/ivtv/ivtv-alsa-pcm.c 
b/drivers/media/pci/ivtv/ivtv-alsa-pcm.c
index e1863dbf4edc..7a9b98bc208b 100644
--- a/drivers/media/pci/ivtv/ivtv-alsa-pcm.c
+++ b/drivers/media/pci/ivtv/ivtv-alsa-pcm.c
@@ -159,6 +159,12 @@ static int snd_ivtv_pcm_capture_open(struct 
snd_pcm_substream *substream)
 
/* Instruct the CX2341[56] to start sending packets */
snd_ivtv_lock(itvsc);
+
+   if (ivtv_init_on_first_open(itv)) {
+   snd_ivtv_unlock(itvsc);
+   return -ENXIO;
+   }
+
s = itv-streams[IVTV_ENC_STREAM_TYPE_PCM];
 
v4l2_fh_init(item.fh, s-vdev);
-- 
1.9.2

--
To unsubscribe from this list: send the line unsubscribe linux-media in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH][RESEND 6/8] ALSA: memalloc: use gen_pool_dma_alloc() to allocate iram buffer

2013-11-04 Thread Takashi Iwai
At Fri, 1 Nov 2013 19:48:19 +0800,
Nicolin Chen wrote:
 
 Since gen_pool_dma_alloc() is introduced, we implement it to simplify code.
 
 Signed-off-by: Nicolin Chen b42...@freescale.com

Acked-by: Takashi Iwai ti...@suse.de


 ---
  sound/core/memalloc.c | 6 +-
  1 file changed, 1 insertion(+), 5 deletions(-)
 
 diff --git a/sound/core/memalloc.c b/sound/core/memalloc.c
 index 9d93f02..5e1c7bc 100644
 --- a/sound/core/memalloc.c
 +++ b/sound/core/memalloc.c
 @@ -184,11 +184,7 @@ static void snd_malloc_dev_iram(struct snd_dma_buffer 
 *dmab, size_t size)
   /* Assign the pool into private_data field */
   dmab-private_data = pool;
  
 - dmab-area = (void *)gen_pool_alloc(pool, size);
 - if (!dmab-area)
 - return;
 -
 - dmab-addr = gen_pool_virt_to_phys(pool, (unsigned long)dmab-area);
 + dmab-area = gen_pool_dma_alloc(pool, size, dmab-addr);
  }
  
  /**
 -- 
 1.8.4
 
 
--
To unsubscribe from this list: send the line unsubscribe linux-media in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH 6/8] ALSA: ppc: keywest: Don't use i2c_client-driver

2013-09-30 Thread Takashi Iwai
At Sun, 29 Sep 2013 10:51:04 +0200,
Lars-Peter Clausen wrote:
 
 The 'driver' field of the i2c_client struct is redundant and is going to be
 removed. Use 'to_i2c_driver(client-dev.driver)' instead to get direct
 access to the i2c_driver struct.
 
 Signed-off-by: Lars-Peter Clausen l...@metafoo.de

Acked-by: Takashi Iwai ti...@suse.de


thanks,

Takashi

 ---
  sound/ppc/keywest.c | 4 ++--
  1 file changed, 2 insertions(+), 2 deletions(-)
 
 diff --git a/sound/ppc/keywest.c b/sound/ppc/keywest.c
 index 01aecc2..0d1c27e 100644
 --- a/sound/ppc/keywest.c
 +++ b/sound/ppc/keywest.c
 @@ -65,7 +65,7 @@ static int keywest_attach_adapter(struct i2c_adapter 
 *adapter)
* already bound. If not it means binding failed, and then there
* is no point in keeping the device instantiated.
*/
 - if (!keywest_ctx-client-driver) {
 + if (!keywest_ctx-client-dev.driver) {
   i2c_unregister_device(keywest_ctx-client);
   keywest_ctx-client = NULL;
   return -ENODEV;
 @@ -76,7 +76,7 @@ static int keywest_attach_adapter(struct i2c_adapter 
 *adapter)
* This is safe because i2c-core holds the core_lock mutex for us.
*/
   list_add_tail(keywest_ctx-client-detected,
 -   keywest_ctx-client-driver-clients);
 +   to_i2c_driver(keywest_ctx-client-dev.driver)-clients);
   return 0;
  }
  
 -- 
 1.8.0
 
--
To unsubscribe from this list: send the line unsubscribe linux-media in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH] [media] sound/pci/Kconfig: select RADIO_ADAPTERS if needed

2013-08-26 Thread Takashi Iwai
At Sat, 24 Aug 2013 08:18:02 -0300,
Mauro Carvalho Chehab wrote:
 
 As reported by kbuild test robot fengguang...@intel.com:
   warning: (SND_ES1968_RADIO  SND_FM801_TEA575X_BOOL) selects 
 RADIO_TEA575X which has unmet direct dependencies (MEDIA_SUPPORT  
 RADIO_ADAPTERS  VIDEO_V4L2)
 
 That happens because a radio driver is selected, without selecting the
 RADIO_ADAPTERS menu.
 
 Reported-by: kbuild test robot fengguang...@intel.com
 Cc: Takashi Iwai ti...@suse.de

Feel free to take my ACK, if any.
  Acked-by: Takashi Iwai ti...@suse.de


thanks,

Takashi


 Signed-off-by: Mauro Carvalho Chehab m.che...@samsung.com
 ---
  sound/pci/Kconfig | 3 +++
  1 file changed, 3 insertions(+)
 
 diff --git a/sound/pci/Kconfig b/sound/pci/Kconfig
 index 9df80ef..46ed9e8 100644
 --- a/sound/pci/Kconfig
 +++ b/sound/pci/Kconfig
 @@ -539,7 +539,9 @@ config SND_ES1968_RADIO
   depends on SND_ES1968
   depends on MEDIA_RADIO_SUPPORT
   depends on VIDEO_V4L2=y || VIDEO_V4L2=SND_ES1968
 + select RADIO_ADAPTERS
   select RADIO_TEA575X
 +
   help
 Say Y here to include support for TEA5757 radio tuner integrated on
 some MediaForte cards (e.g. SF64-PCE2).
 @@ -561,6 +563,7 @@ config SND_FM801_TEA575X_BOOL
   depends on SND_FM801
   depends on MEDIA_RADIO_SUPPORT
   depends on VIDEO_V4L2=y || VIDEO_V4L2=SND_FM801
 + select RADIO_ADAPTERS
   select RADIO_TEA575X
   help
 Say Y here to include support for soundcards based on the ForteMedia
 -- 
 1.8.3.1
 
--
To unsubscribe from this list: send the line unsubscribe linux-media in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [alsa-devel] [PATCH 0/2] tea575x: Move from sound to media

2013-07-29 Thread Takashi Iwai
At Sun, 28 Jul 2013 22:01:42 +0200,
Ondrej Zary wrote:
 
 
 Hello,
 TEA575x is neither a sound device nor an i2c device. Let's finally move it 
 from sound/i2c/other to drivers/media/radio.
 
 Tested with snd-es1968, snd-fm801 and radio-sf16fmr2.

Good to resolve messes there now.

For both patches,
  Acked-by: Takashi Iwai ti...@suse.de

Feel free to move them into media git tree for 3.12 kernel.


thanks,

Takashi
--
To unsubscribe from this list: send the line unsubscribe linux-media in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


  1   2   >