提交 07e4ca50 编写于 作者: T Takashi Iwai 提交者: Jaroslav Kysela

[ALSA] hda-intel - Fix ULI M5461 support

HDA Intel driver
Fix and clean up for the support of ULI M5461
- set CORB/RIRB sizes explicitly
- add workarounds for ULI on ia32
- max number of streams depends on the chip type now
- increase the size of BDL
Signed-off-by: NTakashi Iwai <tiwai@suse.de>
上级 3c10a9d9
master alk-4.19.24 alk-4.19.30 alk-4.19.34 alk-4.19.36 alk-4.19.43 alk-4.19.48 alk-4.19.57 ck-4.19.67 ck-4.19.81 ck-4.19.91 github/fork/deepanshu1422/fix-typo-in-comment github/fork/haosdent/fix-typo linux-next v4.19.91 v4.19.90 v4.19.89 v4.19.88 v4.19.87 v4.19.86 v4.19.85 v4.19.84 v4.19.83 v4.19.82 v4.19.81 v4.19.80 v4.19.79 v4.19.78 v4.19.77 v4.19.76 v4.19.75 v4.19.74 v4.19.73 v4.19.72 v4.19.71 v4.19.70 v4.19.69 v4.19.68 v4.19.67 v4.19.66 v4.19.65 v4.19.64 v4.19.63 v4.19.62 v4.19.61 v4.19.60 v4.19.59 v4.19.58 v4.19.57 v4.19.56 v4.19.55 v4.19.54 v4.19.53 v4.19.52 v4.19.51 v4.19.50 v4.19.49 v4.19.48 v4.19.47 v4.19.46 v4.19.45 v4.19.44 v4.19.43 v4.19.42 v4.19.41 v4.19.40 v4.19.39 v4.19.38 v4.19.37 v4.19.36 v4.19.35 v4.19.34 v4.19.33 v4.19.32 v4.19.31 v4.19.30 v4.19.29 v4.19.28 v4.19.27 v4.19.26 v4.19.25 v4.19.24 v4.19.23 v4.19.22 v4.19.21 v4.19.20 v4.19.19 v4.19.18 v4.19.17 v4.19.16 v4.19.15 v4.19.14 v4.19.13 v4.19.12 v4.19.11 v4.19.10 v4.19.9 v4.19.8 v4.19.7 v4.19.6 v4.19.5 v4.19.4 v4.19.3 v4.19.2 v4.19.1 v4.19 v4.19-rc8 v4.19-rc7 v4.19-rc6 v4.19-rc5 v4.19-rc4 v4.19-rc3 v4.19-rc2 v4.19-rc1 ck-release-21 ck-release-20 ck-release-19.2 ck-release-19.1 ck-release-19 ck-release-18 ck-release-17.2 ck-release-17.1 ck-release-17 ck-release-16 ck-release-15.1 ck-release-15 ck-release-14 ck-release-13.2 ck-release-13 ck-release-12 ck-release-11 ck-release-10 ck-release-9 ck-release-7 alk-release-15 alk-release-14 alk-release-13.2 alk-release-13 alk-release-12 alk-release-11 alk-release-10 alk-release-9 alk-release-7
无相关合并请求
......@@ -72,7 +72,8 @@ MODULE_SUPPORTED_DEVICE("{{Intel, ICH6},"
"{ATI, SB450},"
"{VIA, VT8251},"
"{VIA, VT8237A},"
"{SiS, SIS966}}");
"{SiS, SIS966},"
"{ULI, M5461}}");
MODULE_DESCRIPTION("Intel HDA driver");
#define SFX "hda-intel: "
......@@ -142,9 +143,24 @@ enum { SDI0, SDI1, SDI2, SDI3, SDO0, SDO1, SDO2, SDO3 };
*/
/* max number of SDs */
#define MAX_ICH6_DEV 8
/* ICH, ATI and VIA have 4 playback and 4 capture */
#define ICH6_CAPTURE_INDEX 0
#define ICH6_NUM_CAPTURE 4
#define ICH6_PLAYBACK_INDEX 4
#define ICH6_NUM_PLAYBACK 4
/* ULI has 6 playback and 5 capture */
#define ULI_CAPTURE_INDEX 0
#define ULI_NUM_CAPTURE 5
#define ULI_PLAYBACK_INDEX 5
#define ULI_NUM_PLAYBACK 6
/* this number is statically defined for simplicity */
#define MAX_AZX_DEV 16
/* max number of fragments - we may use more if allocating more pages for BDL */
#define AZX_MAX_FRAG (PAGE_SIZE / (MAX_ICH6_DEV * 16))
#define BDL_SIZE PAGE_ALIGN(8192)
#define AZX_MAX_FRAG (BDL_SIZE / (MAX_AZX_DEV * 16))
/* max buffer size - no h/w limit, you can increase as you like */
#define AZX_MAX_BUF_SIZE (1024*1024*1024)
/* max number of PCM devics per card */
......@@ -201,7 +217,6 @@ enum {
};
/* Defines for ATI HD Audio support in SB450 south bridge */
#define ATI_SB450_HDAUDIO_PCI_DEVICE_ID 0x437b
#define ATI_SB450_HDAUDIO_MISC_CNTR2_ADDR 0x42
#define ATI_SB450_HDAUDIO_ENABLE_SNOOP 0x02
......@@ -259,6 +274,14 @@ struct snd_azx {
snd_card_t *card;
struct pci_dev *pci;
/* chip type specific */
int driver_type;
int playback_streams;
int playback_index_offset;
int capture_streams;
int capture_index_offset;
int num_streams;
/* pci resources */
unsigned long addr;
void __iomem *remap_addr;
......@@ -268,8 +291,8 @@ struct snd_azx {
spinlock_t reg_lock;
struct semaphore open_mutex;
/* streams */
azx_dev_t azx_dev[MAX_ICH6_DEV];
/* streams (x num_streams) */
azx_dev_t *azx_dev;
/* PCM */
unsigned int pcm_devs;
......@@ -293,6 +316,23 @@ struct snd_azx {
unsigned int initialized: 1;
};
/* driver types */
enum {
AZX_DRIVER_ICH,
AZX_DRIVER_ATI,
AZX_DRIVER_VIA,
AZX_DRIVER_SIS,
AZX_DRIVER_ULI,
};
static char *driver_short_names[] __devinitdata = {
[AZX_DRIVER_ICH] = "HDA Intel",
[AZX_DRIVER_ATI] = "HDA ATI SB",
[AZX_DRIVER_VIA] = "HDA VIA VT82xx",
[AZX_DRIVER_SIS] = "HDA SIS966",
[AZX_DRIVER_ULI] = "HDA ULI M5461"
};
/*
* macros for easy use
*/
......@@ -361,6 +401,8 @@ static void azx_init_cmd_io(azx_t *chip)
azx_writel(chip, CORBLBASE, (u32)chip->corb.addr);
azx_writel(chip, CORBUBASE, upper_32bit(chip->corb.addr));
/* set the corb size to 256 entries (ULI requires explicitly) */
azx_writeb(chip, CORBSIZE, 0x02);
/* set the corb write pointer to 0 */
azx_writew(chip, CORBWP, 0);
/* reset the corb hw read pointer */
......@@ -374,6 +416,8 @@ static void azx_init_cmd_io(azx_t *chip)
azx_writel(chip, RIRBLBASE, (u32)chip->rirb.addr);
azx_writel(chip, RIRBUBASE, upper_32bit(chip->rirb.addr));
/* set the rirb size to 256 entries (ULI requires explicitly) */
azx_writeb(chip, RIRBSIZE, 0x02);
/* reset the rirb hw write pointer */
azx_writew(chip, RIRBWP, ICH6_RBRWP_CLR);
/* set N=1, get RIRB response interrupt for new entry */
......@@ -597,7 +641,7 @@ static void azx_int_disable(azx_t *chip)
int i;
/* disable interrupts in stream descriptor */
for (i = 0; i < MAX_ICH6_DEV; i++) {
for (i = 0; i < chip->num_streams; i++) {
azx_dev_t *azx_dev = &chip->azx_dev[i];
azx_sd_writeb(azx_dev, SD_CTL,
azx_sd_readb(azx_dev, SD_CTL) & ~SD_INT_MASK);
......@@ -617,7 +661,7 @@ static void azx_int_clear(azx_t *chip)
int i;
/* clear stream status */
for (i = 0; i < MAX_ICH6_DEV; i++) {
for (i = 0; i < chip->num_streams; i++) {
azx_dev_t *azx_dev = &chip->azx_dev[i];
azx_sd_writeb(azx_dev, SD_STS, SD_INT_MASK);
}
......@@ -687,8 +731,7 @@ static void azx_init_chip(azx_t *chip)
}
/* For ATI SB450 azalia HD audio, we need to enable snoop */
if (chip->pci->vendor == PCI_VENDOR_ID_ATI &&
chip->pci->device == ATI_SB450_HDAUDIO_PCI_DEVICE_ID) {
if (chip->driver_type == AZX_DRIVER_ATI) {
pci_read_config_byte(chip->pci, ATI_SB450_HDAUDIO_MISC_CNTR2_ADDR,
&ati_misc_cntl2);
pci_write_config_byte(chip->pci, ATI_SB450_HDAUDIO_MISC_CNTR2_ADDR,
......@@ -715,7 +758,7 @@ static irqreturn_t azx_interrupt(int irq, void* dev_id, struct pt_regs *regs)
return IRQ_NONE;
}
for (i = 0; i < MAX_ICH6_DEV; i++) {
for (i = 0; i < chip->num_streams; i++) {
azx_dev = &chip->azx_dev[i];
if (status & azx_dev->sd_int_sta_mask) {
azx_sd_writeb(azx_dev, SD_STS, SD_INT_MASK);
......@@ -880,9 +923,15 @@ static int __devinit azx_codec_create(azx_t *chip, const char *model)
/* assign a stream for the PCM */
static inline azx_dev_t *azx_assign_device(azx_t *chip, int stream)
{
int dev, i;
dev = stream == SNDRV_PCM_STREAM_PLAYBACK ? 4 : 0;
for (i = 0; i < 4; i++, dev++)
int dev, i, nums;
if (stream == SNDRV_PCM_STREAM_PLAYBACK) {
dev = chip->playback_index_offset;
nums = chip->playback_streams;
} else {
dev = chip->capture_index_offset;
nums = chip->capture_streams;
}
for (i = 0; i < nums; i++, dev++)
if (! chip->azx_dev[dev].opened) {
chip->azx_dev[dev].opened = 1;
return &chip->azx_dev[dev];
......@@ -1190,7 +1239,7 @@ static int __devinit azx_init_stream(azx_t *chip)
/* initialize each stream (aka device)
* assign the starting bdl address to each stream (device) and initialize
*/
for (i = 0; i < MAX_ICH6_DEV; i++) {
for (i = 0; i < chip->num_streams; i++) {
unsigned int off = sizeof(u32) * (i * AZX_MAX_FRAG * 4);
azx_dev_t *azx_dev = &chip->azx_dev[i];
azx_dev->bdl = (u32 *)(chip->bdl.area + off);
......@@ -1249,7 +1298,7 @@ static int azx_free(azx_t *chip)
if (chip->initialized) {
int i;
for (i = 0; i < MAX_ICH6_DEV; i++)
for (i = 0; i < chip->num_streams; i++)
azx_stream_stop(chip, &chip->azx_dev[i]);
/* disable interrupts */
......@@ -1265,10 +1314,10 @@ static int azx_free(azx_t *chip)
/* wait a little for interrupts to finish */
msleep(1);
iounmap(chip->remap_addr);
}
if (chip->remap_addr)
iounmap(chip->remap_addr);
if (chip->irq >= 0)
free_irq(chip->irq, (void*)chip);
......@@ -1280,6 +1329,7 @@ static int azx_free(azx_t *chip)
snd_dma_free_pages(&chip->posbuf);
pci_release_regions(chip->pci);
pci_disable_device(chip->pci);
kfree(chip->azx_dev);
kfree(chip);
return 0;
......@@ -1294,7 +1344,8 @@ static int azx_dev_free(snd_device_t *device)
* constructor
*/
static int __devinit azx_create(snd_card_t *card, struct pci_dev *pci,
int posfix, azx_t **rchip)
int posfix, int driver_type,
azx_t **rchip)
{
azx_t *chip;
int err = 0;
......@@ -1320,9 +1371,20 @@ static int __devinit azx_create(snd_card_t *card, struct pci_dev *pci,
chip->card = card;
chip->pci = pci;
chip->irq = -1;
chip->driver_type = driver_type;
chip->position_fix = posfix;
#if BITS_PER_LONG != 64
/* Fix up base address on ULI M5461 */
if (chip->driver_type == AZX_DRIVER_ULI) {
u16 tmp3;
pci_read_config_word(pci, 0x40, &tmp3);
pci_write_config_word(pci, 0x40, tmp3 | 0x10);
pci_write_config_dword(pci, PCI_BASE_ADDRESS_1, 0);
}
#endif
if ((err = pci_request_regions(pci, "ICH HD audio")) < 0) {
kfree(chip);
pci_disable_device(pci);
......@@ -1348,16 +1410,37 @@ static int __devinit azx_create(snd_card_t *card, struct pci_dev *pci,
pci_set_master(pci);
synchronize_irq(chip->irq);
switch (chip->driver_type) {
case AZX_DRIVER_ULI:
chip->playback_streams = ULI_NUM_PLAYBACK;
chip->capture_streams = ULI_NUM_CAPTURE;
chip->playback_index_offset = ULI_PLAYBACK_INDEX;
chip->capture_index_offset = ULI_CAPTURE_INDEX;
break;
default:
chip->playback_streams = ICH6_NUM_PLAYBACK;
chip->capture_streams = ICH6_NUM_CAPTURE;
chip->playback_index_offset = ICH6_PLAYBACK_INDEX;
chip->capture_index_offset = ICH6_CAPTURE_INDEX;
break;
}
chip->num_streams = chip->playback_streams + chip->capture_streams;
chip->azx_dev = kcalloc(chip->num_streams, sizeof(*chip->azx_dev), GFP_KERNEL);
if (! chip->azx_dev) {
snd_printk(KERN_ERR "cannot malloc azx_dev\n");
goto errout;
}
/* allocate memory for the BDL for each stream */
if ((err = snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, snd_dma_pci_data(chip->pci),
PAGE_SIZE, &chip->bdl)) < 0) {
BDL_SIZE, &chip->bdl)) < 0) {
snd_printk(KERN_ERR SFX "cannot allocate BDL\n");
goto errout;
}
if (chip->position_fix == POS_FIX_POSBUF) {
/* allocate memory for the position buffer */
if ((err = snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, snd_dma_pci_data(chip->pci),
MAX_ICH6_DEV * 8, &chip->posbuf)) < 0) {
chip->num_streams * 8, &chip->posbuf)) < 0) {
snd_printk(KERN_ERR SFX "cannot allocate posbuf\n");
goto errout;
}
......@@ -1386,6 +1469,10 @@ static int __devinit azx_create(snd_card_t *card, struct pci_dev *pci,
goto errout;
}
strcpy(card->driver, "HDA-Intel");
strcpy(card->shortname, driver_short_names[chip->driver_type]);
sprintf(card->longname, "%s at 0x%lx irq %i", card->shortname, chip->addr, chip->irq);
*rchip = chip;
return 0;
......@@ -1414,15 +1501,12 @@ static int __devinit azx_probe(struct pci_dev *pci, const struct pci_device_id *
return -ENOMEM;
}
if ((err = azx_create(card, pci, position_fix[dev], &chip)) < 0) {
if ((err = azx_create(card, pci, position_fix[dev], pci_id->driver_data,
&chip)) < 0) {
snd_card_free(card);
return err;
}
strcpy(card->driver, "HDA-Intel");
strcpy(card->shortname, "HDA Intel");
sprintf(card->longname, "%s at 0x%lx irq %i", card->shortname, chip->addr, chip->irq);
/* create codec instances */
if ((err = azx_codec_create(chip, model[dev])) < 0) {
snd_card_free(card);
......@@ -1463,13 +1547,13 @@ static void __devexit azx_remove(struct pci_dev *pci)
/* PCI IDs */
static struct pci_device_id azx_ids[] = {
{ 0x8086, 0x2668, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, /* ICH6 */
{ 0x8086, 0x27d8, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, /* ICH7 */
{ 0x8086, 0x269a, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, /* ESB2 */
{ 0x1002, 0x437b, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, /* ATI SB450 */
{ 0x1106, 0x3288, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, /* VIA VT8251/VT8237A */
{ 0x1039, 0x7502, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, /* SIS966 */
{ 0x10b9, 0x5461, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, /* ALI 5461? */
{ 0x8086, 0x2668, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AZX_DRIVER_ICH }, /* ICH6 */
{ 0x8086, 0x27d8, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AZX_DRIVER_ICH }, /* ICH7 */
{ 0x8086, 0x269a, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AZX_DRIVER_ICH }, /* ESB2 */
{ 0x1002, 0x437b, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AZX_DRIVER_ATI }, /* ATI SB450 */
{ 0x1106, 0x3288, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AZX_DRIVER_VIA }, /* VIA VT8251/VT8237A */
{ 0x1039, 0x7502, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AZX_DRIVER_SIS }, /* SIS966 */
{ 0x10b9, 0x5461, PCI_ANY_ID, PCI_ANY_ID, 0, 0, AZX_DRIVER_ULI }, /* ULI M5461 */
{ 0, }
};
MODULE_DEVICE_TABLE(pci, azx_ids);
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册
反馈
建议
客服 返回
顶部