^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) //
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) // Hitachi Audio Controller (AC97) support for SH7760/SH7780
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) //
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) // Copyright (c) 2007 Manuel Lauss <mano@roarinelk.homelinux.net>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) //
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) // dont forget to set IPSEL/OMSEL register bits (in your board code) to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) // enable HAC output pins!
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) /* BIG FAT FIXME: although the SH7760 has 2 independent AC97 units, only
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) * the FIRST can be used since ASoC does not pass any information to the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) * ac97_read/write() functions regarding WHICH unit to use. You'll have
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) * to edit the code a bit to use the other AC97 unit. --mlau
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) #include <linux/init.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) #include <linux/module.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) #include <linux/platform_device.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) #include <linux/interrupt.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) #include <linux/wait.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) #include <linux/delay.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) #include <sound/core.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) #include <sound/pcm.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) #include <sound/ac97_codec.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) #include <sound/initval.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) #include <sound/soc.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) /* regs and bits */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) #define HACCR 0x08
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) #define HACCSAR 0x20
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) #define HACCSDR 0x24
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) #define HACPCML 0x28
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) #define HACPCMR 0x2C
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) #define HACTIER 0x50
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) #define HACTSR 0x54
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) #define HACRIER 0x58
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) #define HACRSR 0x5C
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) #define HACACR 0x60
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) #define CR_CR (1 << 15) /* "codec-ready" indicator */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) #define CR_CDRT (1 << 11) /* cold reset */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) #define CR_WMRT (1 << 10) /* warm reset */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) #define CR_B9 (1 << 9) /* the mysterious "bit 9" */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) #define CR_ST (1 << 5) /* AC97 link start bit */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) #define CSAR_RD (1 << 19) /* AC97 data read bit */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) #define CSAR_WR (0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) #define TSR_CMDAMT (1 << 31)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) #define TSR_CMDDMT (1 << 30)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) #define RSR_STARY (1 << 22)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) #define RSR_STDRY (1 << 21)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) #define ACR_DMARX16 (1 << 30)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) #define ACR_DMATX16 (1 << 29)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) #define ACR_TX12ATOM (1 << 26)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) #define ACR_DMARX20 ((1 << 24) | (1 << 22))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) #define ACR_DMATX20 ((1 << 23) | (1 << 21))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) #define CSDR_SHIFT 4
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) #define CSDR_MASK (0xffff << CSDR_SHIFT)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) #define CSAR_SHIFT 12
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) #define CSAR_MASK (0x7f << CSAR_SHIFT)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) #define AC97_WRITE_RETRY 1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) #define AC97_READ_RETRY 5
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) /* manual-suggested AC97 codec access timeouts (us) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) #define TMO_E1 500 /* 21 < E1 < 1000 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) #define TMO_E2 13 /* 13 < E2 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) #define TMO_E3 21 /* 21 < E3 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) #define TMO_E4 500 /* 21 < E4 < 1000 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) struct hac_priv {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) unsigned long mmio; /* HAC base address */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) } hac_cpu_data[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) #if defined(CONFIG_CPU_SUBTYPE_SH7760)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) .mmio = 0xFE240000,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) .mmio = 0xFE250000,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) #elif defined(CONFIG_CPU_SUBTYPE_SH7780)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) .mmio = 0xFFE40000,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) #else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) #error "Unsupported SuperH SoC"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) #define HACREG(reg) (*(unsigned long *)(hac->mmio + (reg)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) * AC97 read/write flow as outlined in the SH7760 manual (pages 903-906)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) static int hac_get_codec_data(struct hac_priv *hac, unsigned short r,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) unsigned short *v)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) unsigned int to1, to2, i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) unsigned short adr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) for (i = AC97_READ_RETRY; i; i--) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) *v = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) /* wait for HAC to receive something from the codec */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) for (to1 = TMO_E4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) to1 && !(HACREG(HACRSR) & RSR_STARY);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) --to1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) udelay(1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) for (to2 = TMO_E4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) to2 && !(HACREG(HACRSR) & RSR_STDRY);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) --to2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) udelay(1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) if (!to1 && !to2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) return 0; /* codec comm is down */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) adr = ((HACREG(HACCSAR) & CSAR_MASK) >> CSAR_SHIFT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) *v = ((HACREG(HACCSDR) & CSDR_MASK) >> CSDR_SHIFT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) HACREG(HACRSR) &= ~(RSR_STDRY | RSR_STARY);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) if (r == adr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) /* manual says: wait at least 21 usec before retrying */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) udelay(21);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) HACREG(HACRSR) &= ~(RSR_STDRY | RSR_STARY);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) return i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) static unsigned short hac_read_codec_aux(struct hac_priv *hac,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) unsigned short reg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) unsigned short val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) unsigned int i, to;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) for (i = AC97_READ_RETRY; i; i--) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) /* send_read_request */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) local_irq_disable();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) HACREG(HACTSR) &= ~(TSR_CMDAMT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) HACREG(HACCSAR) = (reg << CSAR_SHIFT) | CSAR_RD;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) local_irq_enable();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) for (to = TMO_E3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) to && !(HACREG(HACTSR) & TSR_CMDAMT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) --to)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) udelay(1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) HACREG(HACTSR) &= ~TSR_CMDAMT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) val = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) if (hac_get_codec_data(hac, reg, &val) != 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) return i ? val : ~0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) static void hac_ac97_write(struct snd_ac97 *ac97, unsigned short reg,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) unsigned short val)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) int unit_id = 0 /* ac97->private_data */;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) struct hac_priv *hac = &hac_cpu_data[unit_id];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) unsigned int i, to;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) /* write_codec_aux */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) for (i = AC97_WRITE_RETRY; i; i--) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) /* send_write_request */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) local_irq_disable();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) HACREG(HACTSR) &= ~(TSR_CMDDMT | TSR_CMDAMT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) HACREG(HACCSDR) = (val << CSDR_SHIFT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) HACREG(HACCSAR) = (reg << CSAR_SHIFT) & (~CSAR_RD);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) local_irq_enable();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) /* poll-wait for CMDAMT and CMDDMT */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) for (to = TMO_E1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) to && !(HACREG(HACTSR) & (TSR_CMDAMT|TSR_CMDDMT));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) --to)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) udelay(1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) HACREG(HACTSR) &= ~(TSR_CMDAMT | TSR_CMDDMT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) if (to)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) /* timeout, try again */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) static unsigned short hac_ac97_read(struct snd_ac97 *ac97,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) unsigned short reg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) int unit_id = 0 /* ac97->private_data */;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) struct hac_priv *hac = &hac_cpu_data[unit_id];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) return hac_read_codec_aux(hac, reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) static void hac_ac97_warmrst(struct snd_ac97 *ac97)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) int unit_id = 0 /* ac97->private_data */;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) struct hac_priv *hac = &hac_cpu_data[unit_id];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) unsigned int tmo;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) HACREG(HACCR) = CR_WMRT | CR_ST | CR_B9;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) msleep(10);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) HACREG(HACCR) = CR_ST | CR_B9;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) for (tmo = 1000; (tmo > 0) && !(HACREG(HACCR) & CR_CR); tmo--)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) udelay(1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) if (!tmo)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) printk(KERN_INFO "hac: reset: AC97 link down!\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) /* settings this bit lets us have a conversation with codec */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) HACREG(HACACR) |= ACR_TX12ATOM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) static void hac_ac97_coldrst(struct snd_ac97 *ac97)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) int unit_id = 0 /* ac97->private_data */;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) struct hac_priv *hac;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) hac = &hac_cpu_data[unit_id];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) HACREG(HACCR) = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) HACREG(HACCR) = CR_CDRT | CR_ST | CR_B9;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) msleep(10);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) hac_ac97_warmrst(ac97);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) static struct snd_ac97_bus_ops hac_ac97_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) .read = hac_ac97_read,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) .write = hac_ac97_write,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) .reset = hac_ac97_coldrst,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) .warm_reset = hac_ac97_warmrst,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) static int hac_hw_params(struct snd_pcm_substream *substream,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) struct snd_pcm_hw_params *params,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) struct snd_soc_dai *dai)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) struct hac_priv *hac = &hac_cpu_data[dai->id];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) int d = substream->stream == SNDRV_PCM_STREAM_PLAYBACK ? 0 : 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) switch (params->msbits) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) case 16:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) HACREG(HACACR) |= d ? ACR_DMARX16 : ACR_DMATX16;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) HACREG(HACACR) &= d ? ~ACR_DMARX20 : ~ACR_DMATX20;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) case 20:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) HACREG(HACACR) &= d ? ~ACR_DMARX16 : ~ACR_DMATX16;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) HACREG(HACACR) |= d ? ACR_DMARX20 : ACR_DMATX20;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) pr_debug("hac: invalid depth %d bit\n", params->msbits);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) #define AC97_RATES \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) SNDRV_PCM_RATE_8000_192000
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) #define AC97_FMTS \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) SNDRV_PCM_FMTBIT_S16_LE
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) static const struct snd_soc_dai_ops hac_dai_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) .hw_params = hac_hw_params,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) static struct snd_soc_dai_driver sh4_hac_dai[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) .name = "hac-dai.0",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) .playback = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) .rates = AC97_RATES,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) .formats = AC97_FMTS,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) .channels_min = 2,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) .channels_max = 2,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) .capture = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) .rates = AC97_RATES,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) .formats = AC97_FMTS,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) .channels_min = 2,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) .channels_max = 2,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) .ops = &hac_dai_ops,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) #ifdef CONFIG_CPU_SUBTYPE_SH7760
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) .name = "hac-dai.1",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) .id = 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) .playback = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) .rates = AC97_RATES,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) .formats = AC97_FMTS,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) .channels_min = 2,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) .channels_max = 2,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) .capture = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) .rates = AC97_RATES,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) .formats = AC97_FMTS,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) .channels_min = 2,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) .channels_max = 2,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) .ops = &hac_dai_ops,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) static const struct snd_soc_component_driver sh4_hac_component = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) .name = "sh4-hac",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) static int hac_soc_platform_probe(struct platform_device *pdev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) ret = snd_soc_set_ac97_ops(&hac_ac97_ops);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) if (ret != 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) return devm_snd_soc_register_component(&pdev->dev, &sh4_hac_component,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) sh4_hac_dai, ARRAY_SIZE(sh4_hac_dai));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) static int hac_soc_platform_remove(struct platform_device *pdev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) snd_soc_set_ac97_ops(NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) static struct platform_driver hac_pcm_driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) .driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) .name = "hac-pcm-audio",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) .probe = hac_soc_platform_probe,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) .remove = hac_soc_platform_remove,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) module_platform_driver(hac_pcm_driver);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) MODULE_LICENSE("GPL v2");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) MODULE_DESCRIPTION("SuperH onchip HAC (AC97) audio driver");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344) MODULE_AUTHOR("Manuel Lauss <mano@roarinelk.homelinux.net>");