diff options
author | Krzysztof Helt <krzysztof.h1@wp.pl> | 2006-08-23 05:37:36 -0400 |
---|---|---|
committer | Jaroslav Kysela <perex@suse.cz> | 2006-09-23 04:42:38 -0400 |
commit | ab93c7ae54a81bcecb77608ca89eea140f1d45ad (patch) | |
tree | f9db7fbc303e6f18e54bcaea3d1e9039fe8561d0 /sound/sparc | |
parent | 1be54c824be9b5e163cd83dabdf0ad3ac81c72a8 (diff) |
[ALSA] sparc dbri: hardware constrains added
This patch adds ALSA hardware constrains so stereo is possible
only with 16-bit format. It contains small cleanups to ring
buffered code as well.
Signed-off-by: Krzysztof Helt <krzysztof.h1@wp.pl>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
Signed-off-by: Jaroslav Kysela <perex@suse.cz>
Diffstat (limited to 'sound/sparc')
-rw-r--r-- | sound/sparc/dbri.c | 81 |
1 files changed, 62 insertions, 19 deletions
diff --git a/sound/sparc/dbri.c b/sound/sparc/dbri.c index 3fb2ede80eaf..3e6ad507849d 100644 --- a/sound/sparc/dbri.c +++ b/sound/sparc/dbri.c | |||
@@ -85,7 +85,7 @@ MODULE_PARM_DESC(id, "ID string for Sun DBRI soundcard."); | |||
85 | module_param_array(enable, bool, NULL, 0444); | 85 | module_param_array(enable, bool, NULL, 0444); |
86 | MODULE_PARM_DESC(enable, "Enable Sun DBRI soundcard."); | 86 | MODULE_PARM_DESC(enable, "Enable Sun DBRI soundcard."); |
87 | 87 | ||
88 | #define DBRI_DEBUG | 88 | #undef DBRI_DEBUG |
89 | 89 | ||
90 | #define D_INT (1<<0) | 90 | #define D_INT (1<<0) |
91 | #define D_GEN (1<<1) | 91 | #define D_GEN (1<<1) |
@@ -160,7 +160,7 @@ static struct { | |||
160 | /* { NA, (1 << 4), (5 << 3) }, */ | 160 | /* { NA, (1 << 4), (5 << 3) }, */ |
161 | { 48000, (1 << 4), (6 << 3) }, | 161 | { 48000, (1 << 4), (6 << 3) }, |
162 | { 9600, (1 << 4), (7 << 3) }, | 162 | { 9600, (1 << 4), (7 << 3) }, |
163 | { 5513, (2 << 4), (0 << 3) }, /* Actually 5512.5 */ | 163 | { 5512, (2 << 4), (0 << 3) }, /* Actually 5512.5 */ |
164 | { 11025, (2 << 4), (1 << 3) }, | 164 | { 11025, (2 << 4), (1 << 3) }, |
165 | { 18900, (2 << 4), (2 << 3) }, | 165 | { 18900, (2 << 4), (2 << 3) }, |
166 | { 22050, (2 << 4), (3 << 3) }, | 166 | { 22050, (2 << 4), (3 << 3) }, |
@@ -628,8 +628,6 @@ to send them to the DBRI. | |||
628 | 628 | ||
629 | */ | 629 | */ |
630 | 630 | ||
631 | static void dbri_process_interrupt_buffer(struct snd_dbri * dbri); | ||
632 | |||
633 | #define MAXLOOPS 10 | 631 | #define MAXLOOPS 10 |
634 | /* | 632 | /* |
635 | * Wait for the current command string to execute | 633 | * Wait for the current command string to execute |
@@ -669,15 +667,15 @@ static s32 *dbri_cmdlock(struct snd_dbri * dbri, int len) | |||
669 | } | 667 | } |
670 | 668 | ||
671 | /* | 669 | /* |
672 | * Send prepared cmd string. It works by writting a JMP cmd into | 670 | * Send prepared cmd string. It works by writting a JUMP cmd into |
673 | * the last WAIT cmd and force DBRI to reread the cmd. | 671 | * the last WAIT cmd and force DBRI to reread the cmd. |
674 | * The JMP cmd points to the new cmd string. | 672 | * The JUMP cmd points to the new cmd string. |
675 | * It also releases the cmdlock spinlock. | 673 | * It also releases the cmdlock spinlock. |
676 | */ | 674 | */ |
677 | static void dbri_cmdsend(struct snd_dbri * dbri, s32 * cmd,int len) | 675 | static void dbri_cmdsend(struct snd_dbri * dbri, s32 * cmd,int len) |
678 | { | 676 | { |
679 | s32 *ptr; | ||
680 | s32 tmp, addr; | 677 | s32 tmp, addr; |
678 | unsigned long flags; | ||
681 | static int wait_id = 0; | 679 | static int wait_id = 0; |
682 | 680 | ||
683 | wait_id++; | 681 | wait_id++; |
@@ -691,14 +689,17 @@ static void dbri_cmdsend(struct snd_dbri * dbri, s32 * cmd,int len) | |||
691 | *(dbri->cmdptr) = DBRI_CMD(D_JUMP, 0, 0); | 689 | *(dbri->cmdptr) = DBRI_CMD(D_JUMP, 0, 0); |
692 | 690 | ||
693 | #ifdef DBRI_DEBUG | 691 | #ifdef DBRI_DEBUG |
694 | if (cmd > dbri->cmdptr ) | 692 | if (cmd > dbri->cmdptr) { |
693 | s32 *ptr; | ||
694 | |||
695 | for (ptr = dbri->cmdptr; ptr < cmd+2; ptr++) { | 695 | for (ptr = dbri->cmdptr; ptr < cmd+2; ptr++) { |
696 | dprintk(D_CMD, "cmd: %lx:%08x\n", (unsigned long)ptr, *ptr); | 696 | dprintk(D_CMD, "cmd: %lx:%08x\n", (unsigned long)ptr, *ptr); |
697 | } | 697 | } |
698 | else { | 698 | } else { |
699 | ptr = dbri->cmdptr; | 699 | s32 *ptr = dbri->cmdptr; |
700 | |||
700 | dprintk(D_CMD, "cmd: %lx:%08x\n", (unsigned long)ptr, *ptr); | 701 | dprintk(D_CMD, "cmd: %lx:%08x\n", (unsigned long)ptr, *ptr); |
701 | ptr = dbri->cmdptr+1; | 702 | ptr++; |
702 | dprintk(D_CMD, "cmd: %lx:%08x\n", (unsigned long)ptr, *ptr); | 703 | dprintk(D_CMD, "cmd: %lx:%08x\n", (unsigned long)ptr, *ptr); |
703 | for (ptr = dbri->dma->cmd; ptr < cmd+2; ptr++) { | 704 | for (ptr = dbri->dma->cmd; ptr < cmd+2; ptr++) { |
704 | dprintk(D_CMD, "cmd: %lx:%08x\n", (unsigned long)ptr, *ptr); | 705 | dprintk(D_CMD, "cmd: %lx:%08x\n", (unsigned long)ptr, *ptr); |
@@ -706,10 +707,12 @@ static void dbri_cmdsend(struct snd_dbri * dbri, s32 * cmd,int len) | |||
706 | } | 707 | } |
707 | #endif | 708 | #endif |
708 | 709 | ||
710 | spin_lock_irqsave(&dbri->lock, flags); | ||
709 | /* Reread the last command */ | 711 | /* Reread the last command */ |
710 | tmp = sbus_readl(dbri->regs + REG0); | 712 | tmp = sbus_readl(dbri->regs + REG0); |
711 | tmp |= D_P; | 713 | tmp |= D_P; |
712 | sbus_writel(tmp, dbri->regs + REG0); | 714 | sbus_writel(tmp, dbri->regs + REG0); |
715 | spin_unlock_irqrestore(&dbri->lock, flags); | ||
713 | 716 | ||
714 | dbri->cmdptr = cmd; | 717 | dbri->cmdptr = cmd; |
715 | spin_unlock(&dbri->cmdlock); | 718 | spin_unlock(&dbri->cmdlock); |
@@ -1549,8 +1552,7 @@ static int cs4215_prepare(struct snd_dbri * dbri, unsigned int rate, | |||
1549 | CS4215_BSEL_128 | CS4215_FREQ[freq_idx].xtal; | 1552 | CS4215_BSEL_128 | CS4215_FREQ[freq_idx].xtal; |
1550 | 1553 | ||
1551 | dbri->mm.channels = channels; | 1554 | dbri->mm.channels = channels; |
1552 | /* Stereo bit: 8 bit stereo not working yet. */ | 1555 | if (channels == 2) |
1553 | if ((channels > 1) && (dbri->mm.precision == 16)) | ||
1554 | dbri->mm.ctrl[1] |= CS4215_DFR_STEREO; | 1556 | dbri->mm.ctrl[1] |= CS4215_DFR_STEREO; |
1555 | 1557 | ||
1556 | ret = cs4215_setctrl(dbri); | 1558 | ret = cs4215_setctrl(dbri); |
@@ -1624,7 +1626,7 @@ interrupts are disabled. | |||
1624 | 1626 | ||
1625 | /* xmit_descs() | 1627 | /* xmit_descs() |
1626 | * | 1628 | * |
1627 | * Transmit the current TD's for recording/playing, if needed. | 1629 | * Starts transmiting the current TD's for recording/playing. |
1628 | * For playback, ALSA has filled the DMA memory with new data (we hope). | 1630 | * For playback, ALSA has filled the DMA memory with new data (we hope). |
1629 | */ | 1631 | */ |
1630 | static void xmit_descs(struct snd_dbri *dbri) | 1632 | static void xmit_descs(struct snd_dbri *dbri) |
@@ -1699,9 +1701,9 @@ play: | |||
1699 | * them as available. Stops when the first descriptor is found without | 1701 | * them as available. Stops when the first descriptor is found without |
1700 | * TBC (Transmit Buffer Complete) set, or we've run through them all. | 1702 | * TBC (Transmit Buffer Complete) set, or we've run through them all. |
1701 | * | 1703 | * |
1702 | * The DMA buffers are not released, but re-used. Since the transmit buffer | 1704 | * The DMA buffers are not released. They form a ring buffer and |
1703 | * descriptors are not clobbered, they can be re-submitted as is. This is | 1705 | * they are filled by ALSA while others are transmitted by DMA. |
1704 | * done by the xmit_descs() tasklet above since that could take longer. | 1706 | * |
1705 | */ | 1707 | */ |
1706 | 1708 | ||
1707 | static void transmission_complete_intr(struct snd_dbri * dbri, int pipe) | 1709 | static void transmission_complete_intr(struct snd_dbri * dbri, int pipe) |
@@ -1944,8 +1946,8 @@ static struct snd_pcm_hardware snd_dbri_pcm_hw = { | |||
1944 | SNDRV_PCM_FMTBIT_A_LAW | | 1946 | SNDRV_PCM_FMTBIT_A_LAW | |
1945 | SNDRV_PCM_FMTBIT_U8 | | 1947 | SNDRV_PCM_FMTBIT_U8 | |
1946 | SNDRV_PCM_FMTBIT_S16_BE, | 1948 | SNDRV_PCM_FMTBIT_S16_BE, |
1947 | .rates = SNDRV_PCM_RATE_8000_48000, | 1949 | .rates = SNDRV_PCM_RATE_8000_48000 | SNDRV_PCM_RATE_5512, |
1948 | .rate_min = 8000, | 1950 | .rate_min = 5512, |
1949 | .rate_max = 48000, | 1951 | .rate_max = 48000, |
1950 | .channels_min = 1, | 1952 | .channels_min = 1, |
1951 | .channels_max = 2, | 1953 | .channels_max = 2, |
@@ -1956,6 +1958,39 @@ static struct snd_pcm_hardware snd_dbri_pcm_hw = { | |||
1956 | .periods_max = 1024, | 1958 | .periods_max = 1024, |
1957 | }; | 1959 | }; |
1958 | 1960 | ||
1961 | static int snd_hw_rule_format(struct snd_pcm_hw_params *params, | ||
1962 | struct snd_pcm_hw_rule *rule) | ||
1963 | { | ||
1964 | struct snd_interval *c = hw_param_interval(params, | ||
1965 | SNDRV_PCM_HW_PARAM_CHANNELS); | ||
1966 | struct snd_mask *f = hw_param_mask(params, SNDRV_PCM_HW_PARAM_FORMAT); | ||
1967 | struct snd_mask fmt; | ||
1968 | |||
1969 | snd_mask_any(&fmt); | ||
1970 | if (c->min > 1) { | ||
1971 | fmt.bits[0] &= SNDRV_PCM_FMTBIT_S16_BE; | ||
1972 | return snd_mask_refine(f, &fmt); | ||
1973 | } | ||
1974 | return 0; | ||
1975 | } | ||
1976 | |||
1977 | static int snd_hw_rule_channels(struct snd_pcm_hw_params *params, | ||
1978 | struct snd_pcm_hw_rule *rule) | ||
1979 | { | ||
1980 | struct snd_interval *c = hw_param_interval(params, | ||
1981 | SNDRV_PCM_HW_PARAM_CHANNELS); | ||
1982 | struct snd_mask *f = hw_param_mask(params, SNDRV_PCM_HW_PARAM_FORMAT); | ||
1983 | struct snd_interval ch; | ||
1984 | |||
1985 | snd_interval_any(&ch); | ||
1986 | if (!(f->bits[0] & SNDRV_PCM_FMTBIT_S16_BE)) { | ||
1987 | ch.min = ch.max = 1; | ||
1988 | ch.integer = 1; | ||
1989 | return snd_interval_refine(c, &ch); | ||
1990 | } | ||
1991 | return 0; | ||
1992 | } | ||
1993 | |||
1959 | static int snd_dbri_open(struct snd_pcm_substream *substream) | 1994 | static int snd_dbri_open(struct snd_pcm_substream *substream) |
1960 | { | 1995 | { |
1961 | struct snd_dbri *dbri = snd_pcm_substream_chip(substream); | 1996 | struct snd_dbri *dbri = snd_pcm_substream_chip(substream); |
@@ -1973,6 +2008,14 @@ static int snd_dbri_open(struct snd_pcm_substream *substream) | |||
1973 | info->pipe = -1; | 2008 | info->pipe = -1; |
1974 | spin_unlock_irqrestore(&dbri->lock, flags); | 2009 | spin_unlock_irqrestore(&dbri->lock, flags); |
1975 | 2010 | ||
2011 | snd_pcm_hw_rule_add(runtime,0,SNDRV_PCM_HW_PARAM_CHANNELS, | ||
2012 | snd_hw_rule_format, 0, SNDRV_PCM_HW_PARAM_FORMAT, | ||
2013 | -1); | ||
2014 | snd_pcm_hw_rule_add(runtime,0,SNDRV_PCM_HW_PARAM_FORMAT, | ||
2015 | snd_hw_rule_channels, 0, | ||
2016 | SNDRV_PCM_HW_PARAM_CHANNELS, | ||
2017 | -1); | ||
2018 | |||
1976 | cs4215_open(dbri); | 2019 | cs4215_open(dbri); |
1977 | 2020 | ||
1978 | return 0; | 2021 | return 0; |