diff options
Diffstat (limited to 'sound/arm')
-rw-r--r-- | sound/arm/pxa2xx-ac97.c | 39 |
1 files changed, 22 insertions, 17 deletions
diff --git a/sound/arm/pxa2xx-ac97.c b/sound/arm/pxa2xx-ac97.c index dda64beb202b..3acbc6023d19 100644 --- a/sound/arm/pxa2xx-ac97.c +++ b/sound/arm/pxa2xx-ac97.c | |||
@@ -37,39 +37,47 @@ static DECLARE_MUTEX(car_mutex); | |||
37 | static DECLARE_WAIT_QUEUE_HEAD(gsr_wq); | 37 | static DECLARE_WAIT_QUEUE_HEAD(gsr_wq); |
38 | static volatile long gsr_bits; | 38 | static volatile long gsr_bits; |
39 | 39 | ||
40 | /* | ||
41 | * Beware PXA27x bugs: | ||
42 | * | ||
43 | * o Slot 12 read from modem space will hang controller. | ||
44 | * o CDONE, SDONE interrupt fails after any slot 12 IO. | ||
45 | * | ||
46 | * We therefore have an hybrid approach for waiting on SDONE (interrupt or | ||
47 | * 1 jiffy timeout if interrupt never comes). | ||
48 | */ | ||
49 | |||
40 | static unsigned short pxa2xx_ac97_read(struct snd_ac97 *ac97, unsigned short reg) | 50 | static unsigned short pxa2xx_ac97_read(struct snd_ac97 *ac97, unsigned short reg) |
41 | { | 51 | { |
42 | unsigned short val = -1; | 52 | unsigned short val = -1; |
43 | volatile u32 *reg_addr; | 53 | volatile u32 *reg_addr; |
44 | 54 | ||
45 | down(&car_mutex); | 55 | down(&car_mutex); |
46 | if (CAR & CAR_CAIP) { | ||
47 | printk(KERN_CRIT"%s: CAR_CAIP already set\n", __FUNCTION__); | ||
48 | goto out; | ||
49 | } | ||
50 | 56 | ||
51 | /* set up primary or secondary codec space */ | 57 | /* set up primary or secondary codec space */ |
52 | reg_addr = (ac97->num & 1) ? &SAC_REG_BASE : &PAC_REG_BASE; | 58 | reg_addr = (ac97->num & 1) ? &SAC_REG_BASE : &PAC_REG_BASE; |
53 | reg_addr += (reg >> 1); | 59 | reg_addr += (reg >> 1); |
54 | 60 | ||
55 | /* start read access across the ac97 link */ | 61 | /* start read access across the ac97 link */ |
62 | GSR = GSR_CDONE | GSR_SDONE; | ||
56 | gsr_bits = 0; | 63 | gsr_bits = 0; |
57 | val = *reg_addr; | 64 | val = *reg_addr; |
58 | if (reg == AC97_GPIO_STATUS) | 65 | if (reg == AC97_GPIO_STATUS) |
59 | goto out; | 66 | goto out; |
60 | wait_event_timeout(gsr_wq, gsr_bits & GSR_SDONE, 1); | 67 | if (wait_event_timeout(gsr_wq, (GSR | gsr_bits) & GSR_SDONE, 1) <= 0 && |
61 | if (!gsr_bits & GSR_SDONE) { | 68 | !((GSR | gsr_bits) & GSR_SDONE)) { |
62 | printk(KERN_ERR "%s: read error (ac97_reg=%d GSR=%#lx)\n", | 69 | printk(KERN_ERR "%s: read error (ac97_reg=%d GSR=%#lx)\n", |
63 | __FUNCTION__, reg, gsr_bits); | 70 | __FUNCTION__, reg, GSR | gsr_bits); |
64 | val = -1; | 71 | val = -1; |
65 | goto out; | 72 | goto out; |
66 | } | 73 | } |
67 | 74 | ||
68 | /* valid data now */ | 75 | /* valid data now */ |
76 | GSR = GSR_CDONE | GSR_SDONE; | ||
69 | gsr_bits = 0; | 77 | gsr_bits = 0; |
70 | val = *reg_addr; | 78 | val = *reg_addr; |
71 | /* but we've just started another cycle... */ | 79 | /* but we've just started another cycle... */ |
72 | wait_event_timeout(gsr_wq, gsr_bits & GSR_SDONE, 1); | 80 | wait_event_timeout(gsr_wq, (GSR | gsr_bits) & GSR_SDONE, 1); |
73 | 81 | ||
74 | out: up(&car_mutex); | 82 | out: up(&car_mutex); |
75 | return val; | 83 | return val; |
@@ -81,22 +89,19 @@ static void pxa2xx_ac97_write(struct snd_ac97 *ac97, unsigned short reg, unsigne | |||
81 | 89 | ||
82 | down(&car_mutex); | 90 | down(&car_mutex); |
83 | 91 | ||
84 | if (CAR & CAR_CAIP) { | ||
85 | printk(KERN_CRIT "%s: CAR_CAIP already set\n", __FUNCTION__); | ||
86 | goto out; | ||
87 | } | ||
88 | |||
89 | /* set up primary or secondary codec space */ | 92 | /* set up primary or secondary codec space */ |
90 | reg_addr = (ac97->num & 1) ? &SAC_REG_BASE : &PAC_REG_BASE; | 93 | reg_addr = (ac97->num & 1) ? &SAC_REG_BASE : &PAC_REG_BASE; |
91 | reg_addr += (reg >> 1); | 94 | reg_addr += (reg >> 1); |
95 | |||
96 | GSR = GSR_CDONE | GSR_SDONE; | ||
92 | gsr_bits = 0; | 97 | gsr_bits = 0; |
93 | *reg_addr = val; | 98 | *reg_addr = val; |
94 | wait_event_timeout(gsr_wq, gsr_bits & GSR_CDONE, 1); | 99 | if (wait_event_timeout(gsr_wq, (GSR | gsr_bits) & GSR_CDONE, 1) <= 0 && |
95 | if (!gsr_bits & GSR_SDONE) | 100 | !((GSR | gsr_bits) & GSR_CDONE)) |
96 | printk(KERN_ERR "%s: write error (ac97_reg=%d GSR=%#lx)\n", | 101 | printk(KERN_ERR "%s: write error (ac97_reg=%d GSR=%#lx)\n", |
97 | __FUNCTION__, reg, gsr_bits); | 102 | __FUNCTION__, reg, GSR | gsr_bits); |
98 | 103 | ||
99 | out: up(&car_mutex); | 104 | up(&car_mutex); |
100 | } | 105 | } |
101 | 106 | ||
102 | static void pxa2xx_ac97_reset(struct snd_ac97 *ac97) | 107 | static void pxa2xx_ac97_reset(struct snd_ac97 *ac97) |