2011-10-10 18:09:52 +04:00
/*
*
* Support for CX23885 analog audio capture
*
* ( c ) 2008 Mijhail Moreyra < mijhail . moreyra @ gmail . com >
* Adapted from cx88 - alsa . c
* ( c ) 2009 Steven Toth < stoth @ kernellabs . com >
*
* This program is free software ; you can redistribute it and / or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation ; either version 2 of the License , or
* ( at your option ) any later version .
*
* This program is distributed in the hope that it will be useful ,
* but WITHOUT ANY WARRANTY ; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the
* GNU General Public License for more details .
*/
2016-11-13 14:46:11 +03:00
# include "cx23885.h"
# include "cx23885-reg.h"
2011-10-10 18:09:52 +04:00
# include <linux/module.h>
# include <linux/init.h>
# include <linux/device.h>
# include <linux/interrupt.h>
# include <linux/vmalloc.h>
# include <linux/dma-mapping.h>
# include <linux/pci.h>
# include <asm/delay.h>
# include <sound/core.h>
# include <sound/pcm.h>
# include <sound/pcm_params.h>
# include <sound/control.h>
# include <sound/initval.h>
# include <sound/tlv.h>
# define AUDIO_SRAM_CHANNEL SRAM_CH07
2012-10-27 19:34:10 +04:00
# define dprintk(level, fmt, arg...) do { \
if ( audio_debug + 1 > level ) \
2016-11-13 14:46:11 +03:00
printk ( KERN_DEBUG pr_fmt ( " %s: alsa: " fmt ) , \
chip - > dev - > name , # # arg ) ; \
2012-10-27 19:34:10 +04:00
} while ( 0 )
2011-10-10 18:09:52 +04:00
/****************************************************************************
Module global static vars
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
static unsigned int disable_analog_audio ;
module_param ( disable_analog_audio , int , 0644 ) ;
MODULE_PARM_DESC ( disable_analog_audio , " disable analog audio ALSA driver " ) ;
static unsigned int audio_debug ;
module_param ( audio_debug , int , 0644 ) ;
MODULE_PARM_DESC ( audio_debug , " enable debug messages [analog audio] " ) ;
/****************************************************************************
Board specific funtions
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
/* Constants taken from cx88-reg.h */
# define AUD_INT_DN_RISCI1 (1 << 0)
# define AUD_INT_UP_RISCI1 (1 << 1)
# define AUD_INT_RDS_DN_RISCI1 (1 << 2)
# define AUD_INT_DN_RISCI2 (1 << 4) /* yes, 3 is skipped */
# define AUD_INT_UP_RISCI2 (1 << 5)
# define AUD_INT_RDS_DN_RISCI2 (1 << 6)
# define AUD_INT_DN_SYNC (1 << 12)
# define AUD_INT_UP_SYNC (1 << 13)
# define AUD_INT_RDS_DN_SYNC (1 << 14)
# define AUD_INT_OPC_ERR (1 << 16)
# define AUD_INT_BER_IRQ (1 << 20)
# define AUD_INT_MCHG_IRQ (1 << 21)
# define GP_COUNT_CONTROL_RESET 0x3
2014-04-23 15:27:00 +04:00
static int cx23885_alsa_dma_init ( struct cx23885_audio_dev * chip , int nr_pages )
{
struct cx23885_audio_buffer * buf = chip - > buf ;
struct page * pg ;
int i ;
buf - > vaddr = vmalloc_32 ( nr_pages < < PAGE_SHIFT ) ;
if ( NULL = = buf - > vaddr ) {
dprintk ( 1 , " vmalloc_32(%d pages) failed \n " , nr_pages ) ;
return - ENOMEM ;
}
2018-03-22 22:16:25 +03:00
dprintk ( 1 , " vmalloc is at addr %p, size=%d \n " ,
buf - > vaddr , nr_pages < < PAGE_SHIFT ) ;
2014-04-23 15:27:00 +04:00
memset ( buf - > vaddr , 0 , nr_pages < < PAGE_SHIFT ) ;
buf - > nr_pages = nr_pages ;
treewide: Use array_size() in vzalloc()
The vzalloc() function has no 2-factor argument form, so multiplication
factors need to be wrapped in array_size(). This patch replaces cases of:
vzalloc(a * b)
with:
vzalloc(array_size(a, b))
as well as handling cases of:
vzalloc(a * b * c)
with:
vzalloc(array3_size(a, b, c))
This does, however, attempt to ignore constant size factors like:
vzalloc(4 * 1024)
though any constants defined via macros get caught up in the conversion.
Any factors with a sizeof() of "unsigned char", "char", and "u8" were
dropped, since they're redundant.
The Coccinelle script used for this was:
// Fix redundant parens around sizeof().
@@
type TYPE;
expression THING, E;
@@
(
vzalloc(
- (sizeof(TYPE)) * E
+ sizeof(TYPE) * E
, ...)
|
vzalloc(
- (sizeof(THING)) * E
+ sizeof(THING) * E
, ...)
)
// Drop single-byte sizes and redundant parens.
@@
expression COUNT;
typedef u8;
typedef __u8;
@@
(
vzalloc(
- sizeof(u8) * (COUNT)
+ COUNT
, ...)
|
vzalloc(
- sizeof(__u8) * (COUNT)
+ COUNT
, ...)
|
vzalloc(
- sizeof(char) * (COUNT)
+ COUNT
, ...)
|
vzalloc(
- sizeof(unsigned char) * (COUNT)
+ COUNT
, ...)
|
vzalloc(
- sizeof(u8) * COUNT
+ COUNT
, ...)
|
vzalloc(
- sizeof(__u8) * COUNT
+ COUNT
, ...)
|
vzalloc(
- sizeof(char) * COUNT
+ COUNT
, ...)
|
vzalloc(
- sizeof(unsigned char) * COUNT
+ COUNT
, ...)
)
// 2-factor product with sizeof(type/expression) and identifier or constant.
@@
type TYPE;
expression THING;
identifier COUNT_ID;
constant COUNT_CONST;
@@
(
vzalloc(
- sizeof(TYPE) * (COUNT_ID)
+ array_size(COUNT_ID, sizeof(TYPE))
, ...)
|
vzalloc(
- sizeof(TYPE) * COUNT_ID
+ array_size(COUNT_ID, sizeof(TYPE))
, ...)
|
vzalloc(
- sizeof(TYPE) * (COUNT_CONST)
+ array_size(COUNT_CONST, sizeof(TYPE))
, ...)
|
vzalloc(
- sizeof(TYPE) * COUNT_CONST
+ array_size(COUNT_CONST, sizeof(TYPE))
, ...)
|
vzalloc(
- sizeof(THING) * (COUNT_ID)
+ array_size(COUNT_ID, sizeof(THING))
, ...)
|
vzalloc(
- sizeof(THING) * COUNT_ID
+ array_size(COUNT_ID, sizeof(THING))
, ...)
|
vzalloc(
- sizeof(THING) * (COUNT_CONST)
+ array_size(COUNT_CONST, sizeof(THING))
, ...)
|
vzalloc(
- sizeof(THING) * COUNT_CONST
+ array_size(COUNT_CONST, sizeof(THING))
, ...)
)
// 2-factor product, only identifiers.
@@
identifier SIZE, COUNT;
@@
vzalloc(
- SIZE * COUNT
+ array_size(COUNT, SIZE)
, ...)
// 3-factor product with 1 sizeof(type) or sizeof(expression), with
// redundant parens removed.
@@
expression THING;
identifier STRIDE, COUNT;
type TYPE;
@@
(
vzalloc(
- sizeof(TYPE) * (COUNT) * (STRIDE)
+ array3_size(COUNT, STRIDE, sizeof(TYPE))
, ...)
|
vzalloc(
- sizeof(TYPE) * (COUNT) * STRIDE
+ array3_size(COUNT, STRIDE, sizeof(TYPE))
, ...)
|
vzalloc(
- sizeof(TYPE) * COUNT * (STRIDE)
+ array3_size(COUNT, STRIDE, sizeof(TYPE))
, ...)
|
vzalloc(
- sizeof(TYPE) * COUNT * STRIDE
+ array3_size(COUNT, STRIDE, sizeof(TYPE))
, ...)
|
vzalloc(
- sizeof(THING) * (COUNT) * (STRIDE)
+ array3_size(COUNT, STRIDE, sizeof(THING))
, ...)
|
vzalloc(
- sizeof(THING) * (COUNT) * STRIDE
+ array3_size(COUNT, STRIDE, sizeof(THING))
, ...)
|
vzalloc(
- sizeof(THING) * COUNT * (STRIDE)
+ array3_size(COUNT, STRIDE, sizeof(THING))
, ...)
|
vzalloc(
- sizeof(THING) * COUNT * STRIDE
+ array3_size(COUNT, STRIDE, sizeof(THING))
, ...)
)
// 3-factor product with 2 sizeof(variable), with redundant parens removed.
@@
expression THING1, THING2;
identifier COUNT;
type TYPE1, TYPE2;
@@
(
vzalloc(
- sizeof(TYPE1) * sizeof(TYPE2) * COUNT
+ array3_size(COUNT, sizeof(TYPE1), sizeof(TYPE2))
, ...)
|
vzalloc(
- sizeof(TYPE1) * sizeof(THING2) * (COUNT)
+ array3_size(COUNT, sizeof(TYPE1), sizeof(TYPE2))
, ...)
|
vzalloc(
- sizeof(THING1) * sizeof(THING2) * COUNT
+ array3_size(COUNT, sizeof(THING1), sizeof(THING2))
, ...)
|
vzalloc(
- sizeof(THING1) * sizeof(THING2) * (COUNT)
+ array3_size(COUNT, sizeof(THING1), sizeof(THING2))
, ...)
|
vzalloc(
- sizeof(TYPE1) * sizeof(THING2) * COUNT
+ array3_size(COUNT, sizeof(TYPE1), sizeof(THING2))
, ...)
|
vzalloc(
- sizeof(TYPE1) * sizeof(THING2) * (COUNT)
+ array3_size(COUNT, sizeof(TYPE1), sizeof(THING2))
, ...)
)
// 3-factor product, only identifiers, with redundant parens removed.
@@
identifier STRIDE, SIZE, COUNT;
@@
(
vzalloc(
- (COUNT) * STRIDE * SIZE
+ array3_size(COUNT, STRIDE, SIZE)
, ...)
|
vzalloc(
- COUNT * (STRIDE) * SIZE
+ array3_size(COUNT, STRIDE, SIZE)
, ...)
|
vzalloc(
- COUNT * STRIDE * (SIZE)
+ array3_size(COUNT, STRIDE, SIZE)
, ...)
|
vzalloc(
- (COUNT) * (STRIDE) * SIZE
+ array3_size(COUNT, STRIDE, SIZE)
, ...)
|
vzalloc(
- COUNT * (STRIDE) * (SIZE)
+ array3_size(COUNT, STRIDE, SIZE)
, ...)
|
vzalloc(
- (COUNT) * STRIDE * (SIZE)
+ array3_size(COUNT, STRIDE, SIZE)
, ...)
|
vzalloc(
- (COUNT) * (STRIDE) * (SIZE)
+ array3_size(COUNT, STRIDE, SIZE)
, ...)
|
vzalloc(
- COUNT * STRIDE * SIZE
+ array3_size(COUNT, STRIDE, SIZE)
, ...)
)
// Any remaining multi-factor products, first at least 3-factor products
// when they're not all constants...
@@
expression E1, E2, E3;
constant C1, C2, C3;
@@
(
vzalloc(C1 * C2 * C3, ...)
|
vzalloc(
- E1 * E2 * E3
+ array3_size(E1, E2, E3)
, ...)
)
// And then all remaining 2 factors products when they're not all constants.
@@
expression E1, E2;
constant C1, C2;
@@
(
vzalloc(C1 * C2, ...)
|
vzalloc(
- E1 * E2
+ array_size(E1, E2)
, ...)
)
Signed-off-by: Kees Cook <keescook@chromium.org>
2018-06-13 00:27:37 +03:00
buf - > sglist = vzalloc ( array_size ( sizeof ( * buf - > sglist ) , buf - > nr_pages ) ) ;
2014-04-23 15:27:00 +04:00
if ( NULL = = buf - > sglist )
goto vzalloc_err ;
sg_init_table ( buf - > sglist , buf - > nr_pages ) ;
for ( i = 0 ; i < buf - > nr_pages ; i + + ) {
pg = vmalloc_to_page ( buf - > vaddr + i * PAGE_SIZE ) ;
if ( NULL = = pg )
goto vmalloc_to_page_err ;
sg_set_page ( & buf - > sglist [ i ] , pg , PAGE_SIZE , 0 ) ;
}
return 0 ;
vmalloc_to_page_err :
vfree ( buf - > sglist ) ;
buf - > sglist = NULL ;
vzalloc_err :
vfree ( buf - > vaddr ) ;
buf - > vaddr = NULL ;
return - ENOMEM ;
}
static int cx23885_alsa_dma_map ( struct cx23885_audio_dev * dev )
{
struct cx23885_audio_buffer * buf = dev - > buf ;
buf - > sglen = dma_map_sg ( & dev - > pci - > dev , buf - > sglist ,
buf - > nr_pages , PCI_DMA_FROMDEVICE ) ;
if ( 0 = = buf - > sglen ) {
pr_warn ( " %s: cx23885_alsa_map_sg failed \n " , __func__ ) ;
return - ENOMEM ;
}
return 0 ;
}
static int cx23885_alsa_dma_unmap ( struct cx23885_audio_dev * dev )
{
struct cx23885_audio_buffer * buf = dev - > buf ;
if ( ! buf - > sglen )
return 0 ;
dma_unmap_sg ( & dev - > pci - > dev , buf - > sglist , buf - > sglen , PCI_DMA_FROMDEVICE ) ;
buf - > sglen = 0 ;
return 0 ;
}
static int cx23885_alsa_dma_free ( struct cx23885_audio_buffer * buf )
{
vfree ( buf - > sglist ) ;
buf - > sglist = NULL ;
vfree ( buf - > vaddr ) ;
buf - > vaddr = NULL ;
return 0 ;
}
2011-10-10 18:09:52 +04:00
/*
* BOARD Specific : Sets audio DMA
*/
static int cx23885_start_audio_dma ( struct cx23885_audio_dev * chip )
{
struct cx23885_audio_buffer * buf = chip - > buf ;
struct cx23885_dev * dev = chip - > dev ;
struct sram_channel * audio_ch =
& dev - > sram_channels [ AUDIO_SRAM_CHANNEL ] ;
dprintk ( 1 , " %s() \n " , __func__ ) ;
/* Make sure RISC/FIFO are off before changing FIFO/RISC settings */
cx_clear ( AUD_INT_DMA_CTL , 0x11 ) ;
/* setup fifo + format - out channel */
cx23885_sram_channel_setup ( chip - > dev , audio_ch , buf - > bpl ,
buf - > risc . dma ) ;
/* sets bpl size */
cx_write ( AUD_INT_A_LNGTH , buf - > bpl ) ;
/* This is required to get good audio (1 seems to be ok) */
cx_write ( AUD_INT_A_MODE , 1 ) ;
/* reset counter */
cx_write ( AUD_INT_A_GPCNT_CTL , GP_COUNT_CONTROL_RESET ) ;
atomic_set ( & chip - > count , 0 ) ;
[media] cx23885: don't break long lines
Due to the 80-cols restrictions, and latter due to checkpatch
warnings, several strings were broken into multiple lines. This
is not considered a good practice anymore, as it makes harder
to grep for strings at the source code.
As we're right now fixing other drivers due to KERN_CONT, we need
to be able to identify what printk strings don't end with a "\n".
It is a way easier to detect those if we don't break long lines.
So, join those continuation lines.
The patch was generated via the script below, and manually
adjusted if needed.
</script>
use Text::Tabs;
while (<>) {
if ($next ne "") {
$c=$_;
if ($c =~ /^\s+\"(.*)/) {
$c2=$1;
$next =~ s/\"\n$//;
$n = expand($next);
$funpos = index($n, '(');
$pos = index($c2, '",');
if ($funpos && $pos > 0) {
$s1 = substr $c2, 0, $pos + 2;
$s2 = ' ' x ($funpos + 1) . substr $c2, $pos + 2;
$s2 =~ s/^\s+//;
$s2 = ' ' x ($funpos + 1) . $s2 if ($s2 ne "");
print unexpand("$next$s1\n");
print unexpand("$s2\n") if ($s2 ne "");
} else {
print "$next$c2\n";
}
$next="";
next;
} else {
print $next;
}
$next="";
} else {
if (m/\"$/) {
if (!m/\\n\"$/) {
$next=$_;
next;
}
}
}
print $_;
}
</script>
Signed-off-by: Mauro Carvalho Chehab <mchehab@s-opensource.com>
2016-10-18 22:44:03 +03:00
dprintk ( 1 , " Start audio DMA, %d B/line, %d lines/FIFO, %d periods, %d byte buffer \n " ,
buf - > bpl , cx_read ( audio_ch - > cmds_start + 12 ) > > 1 ,
2011-10-10 18:09:52 +04:00
chip - > num_periods , buf - > bpl * chip - > num_periods ) ;
/* Enables corresponding bits at AUD_INT_STAT */
cx_write ( AUDIO_INT_INT_MSK , AUD_INT_OPC_ERR | AUD_INT_DN_SYNC |
AUD_INT_DN_RISCI1 ) ;
/* Clean any pending interrupt bits already set */
cx_write ( AUDIO_INT_INT_STAT , ~ 0 ) ;
/* enable audio irqs */
cx_set ( PCI_INT_MSK , chip - > dev - > pci_irqmask | PCI_MSK_AUD_INT ) ;
/* start dma */
cx_set ( DEV_CNTRL2 , ( 1 < < 5 ) ) ; /* Enables Risc Processor */
cx_set ( AUD_INT_DMA_CTL , 0x11 ) ; /* audio downstream FIFO and
RISC enable */
if ( audio_debug )
cx23885_sram_channel_dump ( chip - > dev , audio_ch ) ;
return 0 ;
}
/*
* BOARD Specific : Resets audio DMA
*/
static int cx23885_stop_audio_dma ( struct cx23885_audio_dev * chip )
{
struct cx23885_dev * dev = chip - > dev ;
dprintk ( 1 , " Stopping audio DMA \n " ) ;
/* stop dma */
cx_clear ( AUD_INT_DMA_CTL , 0x11 ) ;
/* disable irqs */
cx_clear ( PCI_INT_MSK , PCI_MSK_AUD_INT ) ;
cx_clear ( AUDIO_INT_INT_MSK , AUD_INT_OPC_ERR | AUD_INT_DN_SYNC |
AUD_INT_DN_RISCI1 ) ;
if ( audio_debug )
cx23885_sram_channel_dump ( chip - > dev ,
& dev - > sram_channels [ AUDIO_SRAM_CHANNEL ] ) ;
return 0 ;
}
/*
* BOARD Specific : Handles audio IRQ
*/
int cx23885_audio_irq ( struct cx23885_dev * dev , u32 status , u32 mask )
{
struct cx23885_audio_dev * chip = dev - > audio_dev ;
if ( 0 = = ( status & mask ) )
return 0 ;
cx_write ( AUDIO_INT_INT_STAT , status ) ;
/* risc op code error */
if ( status & AUD_INT_OPC_ERR ) {
2016-11-13 14:46:11 +03:00
pr_warn ( " %s/1: Audio risc op code error \n " ,
2011-10-10 18:09:52 +04:00
dev - > name ) ;
cx_clear ( AUD_INT_DMA_CTL , 0x11 ) ;
cx23885_sram_channel_dump ( dev ,
& dev - > sram_channels [ AUDIO_SRAM_CHANNEL ] ) ;
}
if ( status & AUD_INT_DN_SYNC ) {
dprintk ( 1 , " Downstream sync error \n " ) ;
cx_write ( AUD_INT_A_GPCNT_CTL , GP_COUNT_CONTROL_RESET ) ;
return 1 ;
}
/* risc1 downstream */
if ( status & AUD_INT_DN_RISCI1 ) {
atomic_set ( & chip - > count , cx_read ( AUD_INT_A_GPCNT ) ) ;
snd_pcm_period_elapsed ( chip - > substream ) ;
}
/* FIXME: Any other status should deserve a special handling? */
return 1 ;
}
static int dsp_buffer_free ( struct cx23885_audio_dev * chip )
{
2014-08-10 13:26:01 +04:00
struct cx23885_riscmem * risc ;
2011-10-10 18:09:52 +04:00
BUG_ON ( ! chip - > dma_size ) ;
dprintk ( 2 , " Freeing buffer \n " ) ;
2014-04-23 15:27:00 +04:00
cx23885_alsa_dma_unmap ( chip ) ;
cx23885_alsa_dma_free ( chip - > buf ) ;
2014-08-10 13:26:01 +04:00
risc = & chip - > buf - > risc ;
pci_free_consistent ( chip - > pci , risc - > size , risc - > cpu , risc - > dma ) ;
2011-10-10 18:09:52 +04:00
kfree ( chip - > buf ) ;
2014-04-23 15:27:00 +04:00
chip - > buf = NULL ;
2011-10-10 18:09:52 +04:00
chip - > dma_size = 0 ;
return 0 ;
}
/****************************************************************************
ALSA PCM Interface
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
/*
* Digital hardware definition
*/
# define DEFAULT_FIFO_SIZE 4096
2017-08-13 15:43:09 +03:00
static const struct snd_pcm_hardware snd_cx23885_digital_hw = {
2011-10-10 18:09:52 +04:00
. info = SNDRV_PCM_INFO_MMAP |
SNDRV_PCM_INFO_INTERLEAVED |
SNDRV_PCM_INFO_BLOCK_TRANSFER |
SNDRV_PCM_INFO_MMAP_VALID ,
. formats = SNDRV_PCM_FMTBIT_S16_LE ,
. rates = SNDRV_PCM_RATE_48000 ,
. rate_min = 48000 ,
. rate_max = 48000 ,
. channels_min = 2 ,
. channels_max = 2 ,
/* Analog audio output will be full of clicks and pops if there
are not exactly four lines in the SRAM FIFO buffer . */
. period_bytes_min = DEFAULT_FIFO_SIZE / 4 ,
. period_bytes_max = DEFAULT_FIFO_SIZE / 4 ,
. periods_min = 1 ,
. periods_max = 1024 ,
. buffer_bytes_max = ( 1024 * 1024 ) ,
} ;
/*
* audio pcm capture open callback
*/
static int snd_cx23885_pcm_open ( struct snd_pcm_substream * substream )
{
struct cx23885_audio_dev * chip = snd_pcm_substream_chip ( substream ) ;
struct snd_pcm_runtime * runtime = substream - > runtime ;
int err ;
if ( ! chip ) {
2016-11-13 14:46:11 +03:00
pr_err ( " BUG: cx23885 can't find device struct. Can't proceed with open \n " ) ;
2011-10-10 18:09:52 +04:00
return - ENODEV ;
}
err = snd_pcm_hw_constraint_pow2 ( runtime , 0 ,
SNDRV_PCM_HW_PARAM_PERIODS ) ;
if ( err < 0 )
goto _error ;
chip - > substream = substream ;
runtime - > hw = snd_cx23885_digital_hw ;
if ( chip - > dev - > sram_channels [ AUDIO_SRAM_CHANNEL ] . fifo_size ! =
DEFAULT_FIFO_SIZE ) {
unsigned int bpl = chip - > dev - >
sram_channels [ AUDIO_SRAM_CHANNEL ] . fifo_size / 4 ;
bpl & = ~ 7 ; /* must be multiple of 8 */
runtime - > hw . period_bytes_min = bpl ;
runtime - > hw . period_bytes_max = bpl ;
}
return 0 ;
_error :
dprintk ( 1 , " Error opening PCM! \n " ) ;
return err ;
}
/*
* audio close callback
*/
static int snd_cx23885_close ( struct snd_pcm_substream * substream )
{
return 0 ;
}
2014-04-23 15:27:00 +04:00
2011-10-10 18:09:52 +04:00
/*
* hw_params callback
*/
static int snd_cx23885_hw_params ( struct snd_pcm_substream * substream ,
struct snd_pcm_hw_params * hw_params )
{
struct cx23885_audio_dev * chip = snd_pcm_substream_chip ( substream ) ;
struct cx23885_audio_buffer * buf ;
int ret ;
if ( substream - > runtime - > dma_area ) {
dsp_buffer_free ( chip ) ;
substream - > runtime - > dma_area = NULL ;
}
chip - > period_size = params_period_bytes ( hw_params ) ;
chip - > num_periods = params_periods ( hw_params ) ;
chip - > dma_size = chip - > period_size * params_periods ( hw_params ) ;
BUG_ON ( ! chip - > dma_size ) ;
BUG_ON ( chip - > num_periods & ( chip - > num_periods - 1 ) ) ;
buf = kzalloc ( sizeof ( * buf ) , GFP_KERNEL ) ;
if ( NULL = = buf )
return - ENOMEM ;
buf - > bpl = chip - > period_size ;
2014-08-14 13:43:01 +04:00
chip - > buf = buf ;
2011-10-10 18:09:52 +04:00
2014-04-23 15:27:00 +04:00
ret = cx23885_alsa_dma_init ( chip ,
2011-10-10 18:09:52 +04:00
( PAGE_ALIGN ( chip - > dma_size ) > > PAGE_SHIFT ) ) ;
if ( ret < 0 )
goto error ;
2014-04-23 15:27:00 +04:00
ret = cx23885_alsa_dma_map ( chip ) ;
2011-10-10 18:09:52 +04:00
if ( ret < 0 )
goto error ;
2014-04-23 15:27:00 +04:00
ret = cx23885_risc_databuffer ( chip - > pci , & buf - > risc , buf - > sglist ,
2011-10-10 18:09:52 +04:00
chip - > period_size , chip - > num_periods , 1 ) ;
if ( ret < 0 )
goto error ;
/* Loop back to start of program */
buf - > risc . jmp [ 0 ] = cpu_to_le32 ( RISC_JUMP | RISC_IRQ1 | RISC_CNT_INC ) ;
buf - > risc . jmp [ 1 ] = cpu_to_le32 ( buf - > risc . dma ) ;
buf - > risc . jmp [ 2 ] = cpu_to_le32 ( 0 ) ; /* bits 63-32 */
2014-04-23 15:27:00 +04:00
substream - > runtime - > dma_area = chip - > buf - > vaddr ;
2011-10-10 18:09:52 +04:00
substream - > runtime - > dma_bytes = chip - > dma_size ;
substream - > runtime - > dma_addr = 0 ;
return 0 ;
error :
kfree ( buf ) ;
2014-08-14 13:43:01 +04:00
chip - > buf = NULL ;
2011-10-10 18:09:52 +04:00
return ret ;
}
/*
* hw free callback
*/
static int snd_cx23885_hw_free ( struct snd_pcm_substream * substream )
{
struct cx23885_audio_dev * chip = snd_pcm_substream_chip ( substream ) ;
if ( substream - > runtime - > dma_area ) {
dsp_buffer_free ( chip ) ;
substream - > runtime - > dma_area = NULL ;
}
return 0 ;
}
/*
* prepare callback
*/
static int snd_cx23885_prepare ( struct snd_pcm_substream * substream )
{
return 0 ;
}
/*
* trigger callback
*/
static int snd_cx23885_card_trigger ( struct snd_pcm_substream * substream ,
int cmd )
{
struct cx23885_audio_dev * chip = snd_pcm_substream_chip ( substream ) ;
int err ;
/* Local interrupts are already disabled by ALSA */
spin_lock ( & chip - > lock ) ;
switch ( cmd ) {
case SNDRV_PCM_TRIGGER_START :
err = cx23885_start_audio_dma ( chip ) ;
break ;
case SNDRV_PCM_TRIGGER_STOP :
err = cx23885_stop_audio_dma ( chip ) ;
break ;
default :
err = - EINVAL ;
break ;
}
spin_unlock ( & chip - > lock ) ;
return err ;
}
/*
* pointer callback
*/
static snd_pcm_uframes_t snd_cx23885_pointer (
struct snd_pcm_substream * substream )
{
struct cx23885_audio_dev * chip = snd_pcm_substream_chip ( substream ) ;
struct snd_pcm_runtime * runtime = substream - > runtime ;
u16 count ;
count = atomic_read ( & chip - > count ) ;
return runtime - > period_size * ( count & ( runtime - > periods - 1 ) ) ;
}
/*
* page callback ( needed for mmap )
*/
static struct page * snd_cx23885_page ( struct snd_pcm_substream * substream ,
unsigned long offset )
{
void * pageptr = substream - > runtime - > dma_area + offset ;
return vmalloc_to_page ( pageptr ) ;
}
/*
* operators
*/
2016-09-08 03:44:39 +03:00
static const struct snd_pcm_ops snd_cx23885_pcm_ops = {
2011-10-10 18:09:52 +04:00
. open = snd_cx23885_pcm_open ,
. close = snd_cx23885_close ,
. ioctl = snd_pcm_lib_ioctl ,
. hw_params = snd_cx23885_hw_params ,
. hw_free = snd_cx23885_hw_free ,
. prepare = snd_cx23885_prepare ,
. trigger = snd_cx23885_card_trigger ,
. pointer = snd_cx23885_pointer ,
. page = snd_cx23885_page ,
} ;
/*
* create a PCM device
*/
static int snd_cx23885_pcm ( struct cx23885_audio_dev * chip , int device ,
char * name )
{
int err ;
struct snd_pcm * pcm ;
err = snd_pcm_new ( chip - > card , name , device , 0 , 1 , & pcm ) ;
if ( err < 0 )
return err ;
pcm - > private_data = chip ;
2018-09-10 23:20:42 +03:00
strscpy ( pcm - > name , name , sizeof ( pcm - > name ) ) ;
2011-10-10 18:09:52 +04:00
snd_pcm_set_ops ( pcm , SNDRV_PCM_STREAM_CAPTURE , & snd_cx23885_pcm_ops ) ;
return 0 ;
}
/****************************************************************************
Basic Flow for Sound Devices
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
/*
* Alsa Constructor - Component probe
*/
2011-10-10 18:09:53 +04:00
struct cx23885_audio_dev * cx23885_audio_register ( struct cx23885_dev * dev )
2011-10-10 18:09:52 +04:00
{
struct snd_card * card ;
struct cx23885_audio_dev * chip ;
int err ;
if ( disable_analog_audio )
return NULL ;
if ( dev - > sram_channels [ AUDIO_SRAM_CHANNEL ] . cmds_start = = 0 ) {
2016-11-13 14:46:11 +03:00
pr_warn ( " %s(): Missing SRAM channel configuration for analog TV Audio \n " ,
[media] cx23885: don't break long lines
Due to the 80-cols restrictions, and latter due to checkpatch
warnings, several strings were broken into multiple lines. This
is not considered a good practice anymore, as it makes harder
to grep for strings at the source code.
As we're right now fixing other drivers due to KERN_CONT, we need
to be able to identify what printk strings don't end with a "\n".
It is a way easier to detect those if we don't break long lines.
So, join those continuation lines.
The patch was generated via the script below, and manually
adjusted if needed.
</script>
use Text::Tabs;
while (<>) {
if ($next ne "") {
$c=$_;
if ($c =~ /^\s+\"(.*)/) {
$c2=$1;
$next =~ s/\"\n$//;
$n = expand($next);
$funpos = index($n, '(');
$pos = index($c2, '",');
if ($funpos && $pos > 0) {
$s1 = substr $c2, 0, $pos + 2;
$s2 = ' ' x ($funpos + 1) . substr $c2, $pos + 2;
$s2 =~ s/^\s+//;
$s2 = ' ' x ($funpos + 1) . $s2 if ($s2 ne "");
print unexpand("$next$s1\n");
print unexpand("$s2\n") if ($s2 ne "");
} else {
print "$next$c2\n";
}
$next="";
next;
} else {
print $next;
}
$next="";
} else {
if (m/\"$/) {
if (!m/\\n\"$/) {
$next=$_;
next;
}
}
}
print $_;
}
</script>
Signed-off-by: Mauro Carvalho Chehab <mchehab@s-opensource.com>
2016-10-18 22:44:03 +03:00
__func__ ) ;
2011-10-10 18:09:52 +04:00
return NULL ;
}
2014-01-29 17:48:43 +04:00
err = snd_card_new ( & dev - > pci - > dev ,
SNDRV_DEFAULT_IDX1 , SNDRV_DEFAULT_STR1 ,
2011-10-10 18:09:52 +04:00
THIS_MODULE , sizeof ( struct cx23885_audio_dev ) , & card ) ;
if ( err < 0 )
goto error ;
chip = ( struct cx23885_audio_dev * ) card - > private_data ;
chip - > dev = dev ;
chip - > pci = dev - > pci ;
chip - > card = card ;
spin_lock_init ( & chip - > lock ) ;
err = snd_cx23885_pcm ( chip , 0 , " CX23885 Digital " ) ;
if ( err < 0 )
goto error ;
2018-09-10 23:20:42 +03:00
strscpy ( card - > driver , " CX23885 " , sizeof ( card - > driver ) ) ;
2011-10-10 18:09:52 +04:00
sprintf ( card - > shortname , " Conexant CX23885 " ) ;
sprintf ( card - > longname , " %s at %s " , card - > shortname , dev - > name ) ;
err = snd_card_register ( card ) ;
if ( err < 0 )
goto error ;
dprintk ( 0 , " registered ALSA audio device \n " ) ;
return chip ;
error :
snd_card_free ( card ) ;
2016-11-13 14:46:11 +03:00
pr_err ( " %s(): Failed to register analog audio adapter \n " ,
[media] cx23885: don't break long lines
Due to the 80-cols restrictions, and latter due to checkpatch
warnings, several strings were broken into multiple lines. This
is not considered a good practice anymore, as it makes harder
to grep for strings at the source code.
As we're right now fixing other drivers due to KERN_CONT, we need
to be able to identify what printk strings don't end with a "\n".
It is a way easier to detect those if we don't break long lines.
So, join those continuation lines.
The patch was generated via the script below, and manually
adjusted if needed.
</script>
use Text::Tabs;
while (<>) {
if ($next ne "") {
$c=$_;
if ($c =~ /^\s+\"(.*)/) {
$c2=$1;
$next =~ s/\"\n$//;
$n = expand($next);
$funpos = index($n, '(');
$pos = index($c2, '",');
if ($funpos && $pos > 0) {
$s1 = substr $c2, 0, $pos + 2;
$s2 = ' ' x ($funpos + 1) . substr $c2, $pos + 2;
$s2 =~ s/^\s+//;
$s2 = ' ' x ($funpos + 1) . $s2 if ($s2 ne "");
print unexpand("$next$s1\n");
print unexpand("$s2\n") if ($s2 ne "");
} else {
print "$next$c2\n";
}
$next="";
next;
} else {
print $next;
}
$next="";
} else {
if (m/\"$/) {
if (!m/\\n\"$/) {
$next=$_;
next;
}
}
}
print $_;
}
</script>
Signed-off-by: Mauro Carvalho Chehab <mchehab@s-opensource.com>
2016-10-18 22:44:03 +03:00
__func__ ) ;
2011-10-10 18:09:52 +04:00
return NULL ;
}
/*
* ALSA destructor
*/
2011-10-10 18:09:53 +04:00
void cx23885_audio_unregister ( struct cx23885_dev * dev )
2011-10-10 18:09:52 +04:00
{
struct cx23885_audio_dev * chip = dev - > audio_dev ;
snd_card_free ( chip - > card ) ;
}