Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-only
0002 /*
0003  * Analog Devices ADV7511 HDMI transmitter driver
0004  *
0005  * Copyright 2012 Analog Devices Inc.
0006  * Copyright (c) 2016, Linaro Limited
0007  */
0008 
0009 #include <sound/core.h>
0010 #include <sound/hdmi-codec.h>
0011 #include <sound/pcm.h>
0012 #include <sound/soc.h>
0013 #include <linux/of_graph.h>
0014 
0015 #include "adv7511.h"
0016 
0017 static void adv7511_calc_cts_n(unsigned int f_tmds, unsigned int fs,
0018                    unsigned int *cts, unsigned int *n)
0019 {
0020     switch (fs) {
0021     case 32000:
0022     case 48000:
0023     case 96000:
0024     case 192000:
0025         *n = fs * 128 / 1000;
0026         break;
0027     case 44100:
0028     case 88200:
0029     case 176400:
0030         *n = fs * 128 / 900;
0031         break;
0032     }
0033 
0034     *cts = ((f_tmds * *n) / (128 * fs)) * 1000;
0035 }
0036 
0037 static int adv7511_update_cts_n(struct adv7511 *adv7511)
0038 {
0039     unsigned int cts = 0;
0040     unsigned int n = 0;
0041 
0042     adv7511_calc_cts_n(adv7511->f_tmds, adv7511->f_audio, &cts, &n);
0043 
0044     regmap_write(adv7511->regmap, ADV7511_REG_N0, (n >> 16) & 0xf);
0045     regmap_write(adv7511->regmap, ADV7511_REG_N1, (n >> 8) & 0xff);
0046     regmap_write(adv7511->regmap, ADV7511_REG_N2, n & 0xff);
0047 
0048     regmap_write(adv7511->regmap, ADV7511_REG_CTS_MANUAL0,
0049              (cts >> 16) & 0xf);
0050     regmap_write(adv7511->regmap, ADV7511_REG_CTS_MANUAL1,
0051              (cts >> 8) & 0xff);
0052     regmap_write(adv7511->regmap, ADV7511_REG_CTS_MANUAL2,
0053              cts & 0xff);
0054 
0055     return 0;
0056 }
0057 
0058 static int adv7511_hdmi_hw_params(struct device *dev, void *data,
0059                   struct hdmi_codec_daifmt *fmt,
0060                   struct hdmi_codec_params *hparms)
0061 {
0062     struct adv7511 *adv7511 = dev_get_drvdata(dev);
0063     unsigned int audio_source, i2s_format = 0;
0064     unsigned int invert_clock;
0065     unsigned int rate;
0066     unsigned int len;
0067 
0068     switch (hparms->sample_rate) {
0069     case 32000:
0070         rate = ADV7511_SAMPLE_FREQ_32000;
0071         break;
0072     case 44100:
0073         rate = ADV7511_SAMPLE_FREQ_44100;
0074         break;
0075     case 48000:
0076         rate = ADV7511_SAMPLE_FREQ_48000;
0077         break;
0078     case 88200:
0079         rate = ADV7511_SAMPLE_FREQ_88200;
0080         break;
0081     case 96000:
0082         rate = ADV7511_SAMPLE_FREQ_96000;
0083         break;
0084     case 176400:
0085         rate = ADV7511_SAMPLE_FREQ_176400;
0086         break;
0087     case 192000:
0088         rate = ADV7511_SAMPLE_FREQ_192000;
0089         break;
0090     default:
0091         return -EINVAL;
0092     }
0093 
0094     switch (hparms->sample_width) {
0095     case 16:
0096         len = ADV7511_I2S_SAMPLE_LEN_16;
0097         break;
0098     case 18:
0099         len = ADV7511_I2S_SAMPLE_LEN_18;
0100         break;
0101     case 20:
0102         len = ADV7511_I2S_SAMPLE_LEN_20;
0103         break;
0104     case 32:
0105         if (fmt->bit_fmt != SNDRV_PCM_FORMAT_IEC958_SUBFRAME_LE)
0106             return -EINVAL;
0107         fallthrough;
0108     case 24:
0109         len = ADV7511_I2S_SAMPLE_LEN_24;
0110         break;
0111     default:
0112         return -EINVAL;
0113     }
0114 
0115     switch (fmt->fmt) {
0116     case HDMI_I2S:
0117         audio_source = ADV7511_AUDIO_SOURCE_I2S;
0118         i2s_format = ADV7511_I2S_FORMAT_I2S;
0119         if (fmt->bit_fmt == SNDRV_PCM_FORMAT_IEC958_SUBFRAME_LE)
0120             i2s_format = ADV7511_I2S_IEC958_DIRECT;
0121         break;
0122     case HDMI_RIGHT_J:
0123         audio_source = ADV7511_AUDIO_SOURCE_I2S;
0124         i2s_format = ADV7511_I2S_FORMAT_RIGHT_J;
0125         break;
0126     case HDMI_LEFT_J:
0127         audio_source = ADV7511_AUDIO_SOURCE_I2S;
0128         i2s_format = ADV7511_I2S_FORMAT_LEFT_J;
0129         break;
0130     case HDMI_SPDIF:
0131         audio_source = ADV7511_AUDIO_SOURCE_SPDIF;
0132         break;
0133     default:
0134         return -EINVAL;
0135     }
0136 
0137     invert_clock = fmt->bit_clk_inv;
0138 
0139     regmap_update_bits(adv7511->regmap, ADV7511_REG_AUDIO_SOURCE, 0x70,
0140                audio_source << 4);
0141     regmap_update_bits(adv7511->regmap, ADV7511_REG_AUDIO_CONFIG, BIT(6),
0142                invert_clock << 6);
0143     regmap_update_bits(adv7511->regmap, ADV7511_REG_I2S_CONFIG, 0x03,
0144                i2s_format);
0145 
0146     adv7511->audio_source = audio_source;
0147 
0148     adv7511->f_audio = hparms->sample_rate;
0149 
0150     adv7511_update_cts_n(adv7511);
0151 
0152     regmap_update_bits(adv7511->regmap, ADV7511_REG_AUDIO_CFG3,
0153                ADV7511_AUDIO_CFG3_LEN_MASK, len);
0154     regmap_update_bits(adv7511->regmap, ADV7511_REG_I2C_FREQ_ID_CFG,
0155                ADV7511_I2C_FREQ_ID_CFG_RATE_MASK, rate << 4);
0156     regmap_write(adv7511->regmap, 0x73, 0x1);
0157 
0158     return 0;
0159 }
0160 
0161 static int audio_startup(struct device *dev, void *data)
0162 {
0163     struct adv7511 *adv7511 = dev_get_drvdata(dev);
0164 
0165     regmap_update_bits(adv7511->regmap, ADV7511_REG_AUDIO_CONFIG,
0166                 BIT(7), 0);
0167 
0168     /* hide Audio infoframe updates */
0169     regmap_update_bits(adv7511->regmap, ADV7511_REG_INFOFRAME_UPDATE,
0170                 BIT(5), BIT(5));
0171     /* enable N/CTS, enable Audio sample packets */
0172     regmap_update_bits(adv7511->regmap, ADV7511_REG_PACKET_ENABLE1,
0173                 BIT(5), BIT(5));
0174     /* enable N/CTS */
0175     regmap_update_bits(adv7511->regmap, ADV7511_REG_PACKET_ENABLE1,
0176                 BIT(6), BIT(6));
0177     /* not copyrighted */
0178     regmap_update_bits(adv7511->regmap, ADV7511_REG_AUDIO_CFG1,
0179                 BIT(5), BIT(5));
0180     /* enable audio infoframes */
0181     regmap_update_bits(adv7511->regmap, ADV7511_REG_PACKET_ENABLE1,
0182                 BIT(3), BIT(3));
0183     /* AV mute disable */
0184     regmap_update_bits(adv7511->regmap, ADV7511_REG_GC(0),
0185                 BIT(7) | BIT(6), BIT(7));
0186     /* use Audio infoframe updated info */
0187     regmap_update_bits(adv7511->regmap, ADV7511_REG_GC(1),
0188                 BIT(5), 0);
0189     /* enable SPDIF receiver */
0190     if (adv7511->audio_source == ADV7511_AUDIO_SOURCE_SPDIF)
0191         regmap_update_bits(adv7511->regmap, ADV7511_REG_AUDIO_CONFIG,
0192                    BIT(7), BIT(7));
0193 
0194     return 0;
0195 }
0196 
0197 static void audio_shutdown(struct device *dev, void *data)
0198 {
0199     struct adv7511 *adv7511 = dev_get_drvdata(dev);
0200 
0201     if (adv7511->audio_source == ADV7511_AUDIO_SOURCE_SPDIF)
0202         regmap_update_bits(adv7511->regmap, ADV7511_REG_AUDIO_CONFIG,
0203                    BIT(7), 0);
0204 }
0205 
0206 static int adv7511_hdmi_i2s_get_dai_id(struct snd_soc_component *component,
0207                     struct device_node *endpoint)
0208 {
0209     struct of_endpoint of_ep;
0210     int ret;
0211 
0212     ret = of_graph_parse_endpoint(endpoint, &of_ep);
0213     if (ret < 0)
0214         return ret;
0215 
0216     /*
0217      * HDMI sound should be located as reg = <2>
0218      * Then, it is sound port 0
0219      */
0220     if (of_ep.port == 2)
0221         return 0;
0222 
0223     return -EINVAL;
0224 }
0225 
0226 static const struct hdmi_codec_ops adv7511_codec_ops = {
0227     .hw_params  = adv7511_hdmi_hw_params,
0228     .audio_shutdown = audio_shutdown,
0229     .audio_startup  = audio_startup,
0230     .get_dai_id = adv7511_hdmi_i2s_get_dai_id,
0231 };
0232 
0233 static const struct hdmi_codec_pdata codec_data = {
0234     .ops = &adv7511_codec_ops,
0235     .max_i2s_channels = 2,
0236     .i2s = 1,
0237     .spdif = 1,
0238 };
0239 
0240 int adv7511_audio_init(struct device *dev, struct adv7511 *adv7511)
0241 {
0242     adv7511->audio_pdev = platform_device_register_data(dev,
0243                     HDMI_CODEC_DRV_NAME,
0244                     PLATFORM_DEVID_AUTO,
0245                     &codec_data,
0246                     sizeof(codec_data));
0247     return PTR_ERR_OR_ZERO(adv7511->audio_pdev);
0248 }
0249 
0250 void adv7511_audio_exit(struct adv7511 *adv7511)
0251 {
0252     if (adv7511->audio_pdev) {
0253         platform_device_unregister(adv7511->audio_pdev);
0254         adv7511->audio_pdev = NULL;
0255     }
0256 }