Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0
0002 //
0003 // Hitachi Audio Controller (AC97) support for SH7760/SH7780
0004 //
0005 // Copyright (c) 2007 Manuel Lauss <mano@roarinelk.homelinux.net>
0006 //
0007 // dont forget to set IPSEL/OMSEL register bits (in your board code) to
0008 // enable HAC output pins!
0009 
0010 /* BIG FAT FIXME: although the SH7760 has 2 independent AC97 units, only
0011  * the FIRST can be used since ASoC does not pass any information to the
0012  * ac97_read/write() functions regarding WHICH unit to use.  You'll have
0013  * to edit the code a bit to use the other AC97 unit.       --mlau
0014  */
0015 
0016 #include <linux/init.h>
0017 #include <linux/module.h>
0018 #include <linux/platform_device.h>
0019 #include <linux/interrupt.h>
0020 #include <linux/wait.h>
0021 #include <linux/delay.h>
0022 #include <sound/core.h>
0023 #include <sound/pcm.h>
0024 #include <sound/ac97_codec.h>
0025 #include <sound/initval.h>
0026 #include <sound/soc.h>
0027 
0028 /* regs and bits */
0029 #define HACCR       0x08
0030 #define HACCSAR     0x20
0031 #define HACCSDR     0x24
0032 #define HACPCML     0x28
0033 #define HACPCMR     0x2C
0034 #define HACTIER     0x50
0035 #define HACTSR      0x54
0036 #define HACRIER     0x58
0037 #define HACRSR      0x5C
0038 #define HACACR      0x60
0039 
0040 #define CR_CR       (1 << 15)   /* "codec-ready" indicator */
0041 #define CR_CDRT     (1 << 11)   /* cold reset */
0042 #define CR_WMRT     (1 << 10)   /* warm reset */
0043 #define CR_B9       (1 << 9)    /* the mysterious "bit 9" */
0044 #define CR_ST       (1 << 5)    /* AC97 link start bit */
0045 
0046 #define CSAR_RD     (1 << 19)   /* AC97 data read bit */
0047 #define CSAR_WR     (0)
0048 
0049 #define TSR_CMDAMT  (1 << 31)
0050 #define TSR_CMDDMT  (1 << 30)
0051 
0052 #define RSR_STARY   (1 << 22)
0053 #define RSR_STDRY   (1 << 21)
0054 
0055 #define ACR_DMARX16 (1 << 30)
0056 #define ACR_DMATX16 (1 << 29)
0057 #define ACR_TX12ATOM    (1 << 26)
0058 #define ACR_DMARX20 ((1 << 24) | (1 << 22))
0059 #define ACR_DMATX20 ((1 << 23) | (1 << 21))
0060 
0061 #define CSDR_SHIFT  4
0062 #define CSDR_MASK   (0xffff << CSDR_SHIFT)
0063 #define CSAR_SHIFT  12
0064 #define CSAR_MASK   (0x7f << CSAR_SHIFT)
0065 
0066 #define AC97_WRITE_RETRY    1
0067 #define AC97_READ_RETRY     5
0068 
0069 /* manual-suggested AC97 codec access timeouts (us) */
0070 #define TMO_E1  500 /* 21 < E1 < 1000 */
0071 #define TMO_E2  13  /* 13 < E2 */
0072 #define TMO_E3  21  /* 21 < E3 */
0073 #define TMO_E4  500 /* 21 < E4 < 1000 */
0074 
0075 struct hac_priv {
0076     unsigned long mmio; /* HAC base address */
0077 } hac_cpu_data[] = {
0078 #if defined(CONFIG_CPU_SUBTYPE_SH7760)
0079     {
0080         .mmio   = 0xFE240000,
0081     },
0082     {
0083         .mmio   = 0xFE250000,
0084     },
0085 #elif defined(CONFIG_CPU_SUBTYPE_SH7780)
0086     {
0087         .mmio   = 0xFFE40000,
0088     },
0089 #else
0090 #error "Unsupported SuperH SoC"
0091 #endif
0092 };
0093 
0094 #define HACREG(reg) (*(unsigned long *)(hac->mmio + (reg)))
0095 
0096 /*
0097  * AC97 read/write flow as outlined in the SH7760 manual (pages 903-906)
0098  */
0099 static int hac_get_codec_data(struct hac_priv *hac, unsigned short r,
0100                   unsigned short *v)
0101 {
0102     unsigned int to1, to2, i;
0103     unsigned short adr;
0104 
0105     for (i = AC97_READ_RETRY; i; i--) {
0106         *v = 0;
0107         /* wait for HAC to receive something from the codec */
0108         for (to1 = TMO_E4;
0109              to1 && !(HACREG(HACRSR) & RSR_STARY);
0110              --to1)
0111             udelay(1);
0112         for (to2 = TMO_E4; 
0113              to2 && !(HACREG(HACRSR) & RSR_STDRY);
0114              --to2)
0115             udelay(1);
0116 
0117         if (!to1 && !to2)
0118             return 0;   /* codec comm is down */
0119 
0120         adr = ((HACREG(HACCSAR) & CSAR_MASK) >> CSAR_SHIFT);
0121         *v  = ((HACREG(HACCSDR) & CSDR_MASK) >> CSDR_SHIFT);
0122 
0123         HACREG(HACRSR) &= ~(RSR_STDRY | RSR_STARY);
0124 
0125         if (r == adr)
0126             break;
0127 
0128         /* manual says: wait at least 21 usec before retrying */
0129         udelay(21);
0130     }
0131     HACREG(HACRSR) &= ~(RSR_STDRY | RSR_STARY);
0132     return i;
0133 }
0134 
0135 static unsigned short hac_read_codec_aux(struct hac_priv *hac,
0136                      unsigned short reg)
0137 {
0138     unsigned short val;
0139     unsigned int i, to;
0140 
0141     for (i = AC97_READ_RETRY; i; i--) {
0142         /* send_read_request */
0143         local_irq_disable();
0144         HACREG(HACTSR) &= ~(TSR_CMDAMT);
0145         HACREG(HACCSAR) = (reg << CSAR_SHIFT) | CSAR_RD;
0146         local_irq_enable();
0147 
0148         for (to = TMO_E3;
0149              to && !(HACREG(HACTSR) & TSR_CMDAMT);
0150              --to)
0151             udelay(1);
0152 
0153         HACREG(HACTSR) &= ~TSR_CMDAMT;
0154         val = 0;
0155         if (hac_get_codec_data(hac, reg, &val) != 0)
0156             break;
0157     }
0158 
0159     return i ? val : ~0;
0160 }
0161 
0162 static void hac_ac97_write(struct snd_ac97 *ac97, unsigned short reg,
0163                unsigned short val)
0164 {
0165     int unit_id = 0 /* ac97->private_data */;
0166     struct hac_priv *hac = &hac_cpu_data[unit_id];
0167     unsigned int i, to;
0168     /* write_codec_aux */
0169     for (i = AC97_WRITE_RETRY; i; i--) {
0170         /* send_write_request */
0171         local_irq_disable();
0172         HACREG(HACTSR) &= ~(TSR_CMDDMT | TSR_CMDAMT);
0173         HACREG(HACCSDR) = (val << CSDR_SHIFT);
0174         HACREG(HACCSAR) = (reg << CSAR_SHIFT) & (~CSAR_RD);
0175         local_irq_enable();
0176 
0177         /* poll-wait for CMDAMT and CMDDMT */
0178         for (to = TMO_E1;
0179              to && !(HACREG(HACTSR) & (TSR_CMDAMT|TSR_CMDDMT));
0180              --to)
0181             udelay(1);
0182 
0183         HACREG(HACTSR) &= ~(TSR_CMDAMT | TSR_CMDDMT);
0184         if (to)
0185             break;
0186         /* timeout, try again */
0187     }
0188 }
0189 
0190 static unsigned short hac_ac97_read(struct snd_ac97 *ac97,
0191                     unsigned short reg)
0192 {
0193     int unit_id = 0 /* ac97->private_data */;
0194     struct hac_priv *hac = &hac_cpu_data[unit_id];
0195     return hac_read_codec_aux(hac, reg);
0196 }
0197 
0198 static void hac_ac97_warmrst(struct snd_ac97 *ac97)
0199 {
0200     int unit_id = 0 /* ac97->private_data */;
0201     struct hac_priv *hac = &hac_cpu_data[unit_id];
0202     unsigned int tmo;
0203 
0204     HACREG(HACCR) = CR_WMRT | CR_ST | CR_B9;
0205     msleep(10);
0206     HACREG(HACCR) = CR_ST | CR_B9;
0207     for (tmo = 1000; (tmo > 0) && !(HACREG(HACCR) & CR_CR); tmo--)
0208         udelay(1);
0209 
0210     if (!tmo)
0211         printk(KERN_INFO "hac: reset: AC97 link down!\n");
0212     /* settings this bit lets us have a conversation with codec */
0213     HACREG(HACACR) |= ACR_TX12ATOM;
0214 }
0215 
0216 static void hac_ac97_coldrst(struct snd_ac97 *ac97)
0217 {
0218     int unit_id = 0 /* ac97->private_data */;
0219     struct hac_priv *hac;
0220     hac = &hac_cpu_data[unit_id];
0221 
0222     HACREG(HACCR) = 0;
0223     HACREG(HACCR) = CR_CDRT | CR_ST | CR_B9;
0224     msleep(10);
0225     hac_ac97_warmrst(ac97);
0226 }
0227 
0228 static struct snd_ac97_bus_ops hac_ac97_ops = {
0229     .read   = hac_ac97_read,
0230     .write  = hac_ac97_write,
0231     .reset  = hac_ac97_coldrst,
0232     .warm_reset = hac_ac97_warmrst,
0233 };
0234 
0235 static int hac_hw_params(struct snd_pcm_substream *substream,
0236              struct snd_pcm_hw_params *params,
0237              struct snd_soc_dai *dai)
0238 {
0239     struct hac_priv *hac = &hac_cpu_data[dai->id];
0240     int d = substream->stream == SNDRV_PCM_STREAM_PLAYBACK ? 0 : 1;
0241 
0242     switch (params->msbits) {
0243     case 16:
0244         HACREG(HACACR) |= d ?  ACR_DMARX16 :  ACR_DMATX16;
0245         HACREG(HACACR) &= d ? ~ACR_DMARX20 : ~ACR_DMATX20;
0246         break;
0247     case 20:
0248         HACREG(HACACR) &= d ? ~ACR_DMARX16 : ~ACR_DMATX16;
0249         HACREG(HACACR) |= d ?  ACR_DMARX20 :  ACR_DMATX20;
0250         break;
0251     default:
0252         pr_debug("hac: invalid depth %d bit\n", params->msbits);
0253         return -EINVAL;
0254         break;
0255     }
0256 
0257     return 0;
0258 }
0259 
0260 #define AC97_RATES  \
0261     SNDRV_PCM_RATE_8000_192000
0262 
0263 #define AC97_FMTS   \
0264     SNDRV_PCM_FMTBIT_S16_LE
0265 
0266 static const struct snd_soc_dai_ops hac_dai_ops = {
0267     .hw_params  = hac_hw_params,
0268 };
0269 
0270 static struct snd_soc_dai_driver sh4_hac_dai[] = {
0271 {
0272     .name           = "hac-dai.0",
0273     .playback = {
0274         .rates      = AC97_RATES,
0275         .formats    = AC97_FMTS,
0276         .channels_min   = 2,
0277         .channels_max   = 2,
0278     },
0279     .capture = {
0280         .rates      = AC97_RATES,
0281         .formats    = AC97_FMTS,
0282         .channels_min   = 2,
0283         .channels_max   = 2,
0284     },
0285     .ops = &hac_dai_ops,
0286 },
0287 #ifdef CONFIG_CPU_SUBTYPE_SH7760
0288 {
0289     .name           = "hac-dai.1",
0290     .id         = 1,
0291     .playback = {
0292         .rates      = AC97_RATES,
0293         .formats    = AC97_FMTS,
0294         .channels_min   = 2,
0295         .channels_max   = 2,
0296     },
0297     .capture = {
0298         .rates      = AC97_RATES,
0299         .formats    = AC97_FMTS,
0300         .channels_min   = 2,
0301         .channels_max   = 2,
0302     },
0303     .ops = &hac_dai_ops,
0304 
0305 },
0306 #endif
0307 };
0308 
0309 static const struct snd_soc_component_driver sh4_hac_component = {
0310     .name           = "sh4-hac",
0311     .legacy_dai_naming  = 1,
0312 };
0313 
0314 static int hac_soc_platform_probe(struct platform_device *pdev)
0315 {
0316     int ret;
0317 
0318     ret = snd_soc_set_ac97_ops(&hac_ac97_ops);
0319     if (ret != 0)
0320         return ret;
0321 
0322     return devm_snd_soc_register_component(&pdev->dev, &sh4_hac_component,
0323                       sh4_hac_dai, ARRAY_SIZE(sh4_hac_dai));
0324 }
0325 
0326 static int hac_soc_platform_remove(struct platform_device *pdev)
0327 {
0328     snd_soc_set_ac97_ops(NULL);
0329     return 0;
0330 }
0331 
0332 static struct platform_driver hac_pcm_driver = {
0333     .driver = {
0334             .name = "hac-pcm-audio",
0335     },
0336 
0337     .probe = hac_soc_platform_probe,
0338     .remove = hac_soc_platform_remove,
0339 };
0340 
0341 module_platform_driver(hac_pcm_driver);
0342 
0343 MODULE_LICENSE("GPL v2");
0344 MODULE_DESCRIPTION("SuperH onchip HAC (AC97) audio driver");
0345 MODULE_AUTHOR("Manuel Lauss <mano@roarinelk.homelinux.net>");