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