static void au1xac97c_ac97_write(struct snd_ac97 *ac97, unsigned short r, unsigned short v) { struct au1xpsc_audio_data *ctx = ac97_to_ctx(ac97); unsigned int tmo, retry; retry = AC97_RW_RETRIES; do { mutex_lock(&ctx->lock); for (tmo = 5; (RD(ctx, AC97_STATUS) & STAT_CP) && tmo; tmo--) udelay(21); if (!tmo) { pr_debug("ac97wr timeout #1\n"); goto next; } WR(ctx, AC97_CMDRESP, CMD_WRITE | CMD_IDX(r) | CMD_SET_DATA(v)); for (tmo = 10; (RD(ctx, AC97_STATUS) & STAT_CP) && tmo; tmo--) udelay(21); if (!tmo) pr_debug("ac97wr timeout #2\n"); next: mutex_unlock(&ctx->lock); } while (--retry && !tmo); pr_debug("AC97WR %04x %04x %d\n", r, v, retry); }
static unsigned short au1xac97c_ac97_read(struct snd_ac97 *ac97, unsigned short r) { struct au1xpsc_audio_data *ctx = ac97_to_ctx(ac97); unsigned int tmo, retry; unsigned long data; data = ~0; retry = AC97_RW_RETRIES; do { mutex_lock(&ctx->lock); tmo = 5; while ((RD(ctx, AC97_STATUS) & STAT_CP) && tmo--) udelay(21); /* wait an ac97 frame time */ if (!tmo) { pr_debug("ac97rd timeout #1\n"); goto next; } WR(ctx, AC97_CMDRESP, CMD_IDX(r) | CMD_READ); /* stupid errata: data is only valid for 21us, so * poll, Forrest, poll... */ tmo = 0x10000; while ((RD(ctx, AC97_STATUS) & STAT_CP) && tmo--) asm volatile ("nop"); data = RD(ctx, AC97_CMDRESP); if (!tmo) pr_debug("ac97rd timeout #2\n"); next: mutex_unlock(&ctx->lock); } while (--retry && !tmo); pr_debug("AC97RD %04x %04lx %d\n", r, data, retry); return retry ? data & 0xffff : 0xffff; }