root/drivers/gpu/drm/bridge/adv7511/adv7511_audio.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. adv7511_calc_cts_n
  2. adv7511_update_cts_n
  3. adv7511_hdmi_hw_params
  4. audio_startup
  5. audio_shutdown
  6. adv7511_hdmi_i2s_get_dai_id
  7. adv7511_audio_init
  8. adv7511_audio_exit

   1 // SPDX-License-Identifier: GPL-2.0-only
   2 /*
   3  * Analog Devices ADV7511 HDMI transmitter driver
   4  *
   5  * Copyright 2012 Analog Devices Inc.
   6  * Copyright (c) 2016, Linaro Limited
   7  */
   8 
   9 #include <sound/core.h>
  10 #include <sound/hdmi-codec.h>
  11 #include <sound/pcm.h>
  12 #include <sound/soc.h>
  13 #include <linux/of_graph.h>
  14 
  15 #include "adv7511.h"
  16 
  17 static void adv7511_calc_cts_n(unsigned int f_tmds, unsigned int fs,
  18                                unsigned int *cts, unsigned int *n)
  19 {
  20         switch (fs) {
  21         case 32000:
  22                 *n = 4096;
  23                 break;
  24         case 44100:
  25                 *n = 6272;
  26                 break;
  27         case 48000:
  28                 *n = 6144;
  29                 break;
  30         }
  31 
  32         *cts = ((f_tmds * *n) / (128 * fs)) * 1000;
  33 }
  34 
  35 static int adv7511_update_cts_n(struct adv7511 *adv7511)
  36 {
  37         unsigned int cts = 0;
  38         unsigned int n = 0;
  39 
  40         adv7511_calc_cts_n(adv7511->f_tmds, adv7511->f_audio, &cts, &n);
  41 
  42         regmap_write(adv7511->regmap, ADV7511_REG_N0, (n >> 16) & 0xf);
  43         regmap_write(adv7511->regmap, ADV7511_REG_N1, (n >> 8) & 0xff);
  44         regmap_write(adv7511->regmap, ADV7511_REG_N2, n & 0xff);
  45 
  46         regmap_write(adv7511->regmap, ADV7511_REG_CTS_MANUAL0,
  47                      (cts >> 16) & 0xf);
  48         regmap_write(adv7511->regmap, ADV7511_REG_CTS_MANUAL1,
  49                      (cts >> 8) & 0xff);
  50         regmap_write(adv7511->regmap, ADV7511_REG_CTS_MANUAL2,
  51                      cts & 0xff);
  52 
  53         return 0;
  54 }
  55 
  56 int adv7511_hdmi_hw_params(struct device *dev, void *data,
  57                            struct hdmi_codec_daifmt *fmt,
  58                            struct hdmi_codec_params *hparms)
  59 {
  60         struct adv7511 *adv7511 = dev_get_drvdata(dev);
  61         unsigned int audio_source, i2s_format = 0;
  62         unsigned int invert_clock;
  63         unsigned int rate;
  64         unsigned int len;
  65 
  66         switch (hparms->sample_rate) {
  67         case 32000:
  68                 rate = ADV7511_SAMPLE_FREQ_32000;
  69                 break;
  70         case 44100:
  71                 rate = ADV7511_SAMPLE_FREQ_44100;
  72                 break;
  73         case 48000:
  74                 rate = ADV7511_SAMPLE_FREQ_48000;
  75                 break;
  76         case 88200:
  77                 rate = ADV7511_SAMPLE_FREQ_88200;
  78                 break;
  79         case 96000:
  80                 rate = ADV7511_SAMPLE_FREQ_96000;
  81                 break;
  82         case 176400:
  83                 rate = ADV7511_SAMPLE_FREQ_176400;
  84                 break;
  85         case 192000:
  86                 rate = ADV7511_SAMPLE_FREQ_192000;
  87                 break;
  88         default:
  89                 return -EINVAL;
  90         }
  91 
  92         switch (hparms->sample_width) {
  93         case 16:
  94                 len = ADV7511_I2S_SAMPLE_LEN_16;
  95                 break;
  96         case 18:
  97                 len = ADV7511_I2S_SAMPLE_LEN_18;
  98                 break;
  99         case 20:
 100                 len = ADV7511_I2S_SAMPLE_LEN_20;
 101                 break;
 102         case 24:
 103                 len = ADV7511_I2S_SAMPLE_LEN_24;
 104                 break;
 105         default:
 106                 return -EINVAL;
 107         }
 108 
 109         switch (fmt->fmt) {
 110         case HDMI_I2S:
 111                 audio_source = ADV7511_AUDIO_SOURCE_I2S;
 112                 i2s_format = ADV7511_I2S_FORMAT_I2S;
 113                 break;
 114         case HDMI_RIGHT_J:
 115                 audio_source = ADV7511_AUDIO_SOURCE_I2S;
 116                 i2s_format = ADV7511_I2S_FORMAT_RIGHT_J;
 117                 break;
 118         case HDMI_LEFT_J:
 119                 audio_source = ADV7511_AUDIO_SOURCE_I2S;
 120                 i2s_format = ADV7511_I2S_FORMAT_LEFT_J;
 121                 break;
 122         default:
 123                 return -EINVAL;
 124         }
 125 
 126         invert_clock = fmt->bit_clk_inv;
 127 
 128         regmap_update_bits(adv7511->regmap, ADV7511_REG_AUDIO_SOURCE, 0x70,
 129                            audio_source << 4);
 130         regmap_update_bits(adv7511->regmap, ADV7511_REG_AUDIO_CONFIG, BIT(6),
 131                            invert_clock << 6);
 132         regmap_update_bits(adv7511->regmap, ADV7511_REG_I2S_CONFIG, 0x03,
 133                            i2s_format);
 134 
 135         adv7511->audio_source = audio_source;
 136 
 137         adv7511->f_audio = hparms->sample_rate;
 138 
 139         adv7511_update_cts_n(adv7511);
 140 
 141         regmap_update_bits(adv7511->regmap, ADV7511_REG_AUDIO_CFG3,
 142                            ADV7511_AUDIO_CFG3_LEN_MASK, len);
 143         regmap_update_bits(adv7511->regmap, ADV7511_REG_I2C_FREQ_ID_CFG,
 144                            ADV7511_I2C_FREQ_ID_CFG_RATE_MASK, rate << 4);
 145         regmap_write(adv7511->regmap, 0x73, 0x1);
 146 
 147         return 0;
 148 }
 149 
 150 static int audio_startup(struct device *dev, void *data)
 151 {
 152         struct adv7511 *adv7511 = dev_get_drvdata(dev);
 153 
 154         regmap_update_bits(adv7511->regmap, ADV7511_REG_AUDIO_CONFIG,
 155                                 BIT(7), 0);
 156 
 157         /* hide Audio infoframe updates */
 158         regmap_update_bits(adv7511->regmap, ADV7511_REG_INFOFRAME_UPDATE,
 159                                 BIT(5), BIT(5));
 160         /* enable N/CTS, enable Audio sample packets */
 161         regmap_update_bits(adv7511->regmap, ADV7511_REG_PACKET_ENABLE1,
 162                                 BIT(5), BIT(5));
 163         /* enable N/CTS */
 164         regmap_update_bits(adv7511->regmap, ADV7511_REG_PACKET_ENABLE1,
 165                                 BIT(6), BIT(6));
 166         /* not copyrighted */
 167         regmap_update_bits(adv7511->regmap, ADV7511_REG_AUDIO_CFG1,
 168                                 BIT(5), BIT(5));
 169         /* enable audio infoframes */
 170         regmap_update_bits(adv7511->regmap, ADV7511_REG_PACKET_ENABLE1,
 171                                 BIT(3), BIT(3));
 172         /* AV mute disable */
 173         regmap_update_bits(adv7511->regmap, ADV7511_REG_GC(0),
 174                                 BIT(7) | BIT(6), BIT(7));
 175         /* use Audio infoframe updated info */
 176         regmap_update_bits(adv7511->regmap, ADV7511_REG_GC(1),
 177                                 BIT(5), 0);
 178         return 0;
 179 }
 180 
 181 static void audio_shutdown(struct device *dev, void *data)
 182 {
 183 }
 184 
 185 static int adv7511_hdmi_i2s_get_dai_id(struct snd_soc_component *component,
 186                                         struct device_node *endpoint)
 187 {
 188         struct of_endpoint of_ep;
 189         int ret;
 190 
 191         ret = of_graph_parse_endpoint(endpoint, &of_ep);
 192         if (ret < 0)
 193                 return ret;
 194 
 195         /*
 196          * HDMI sound should be located as reg = <2>
 197          * Then, it is sound port 0
 198          */
 199         if (of_ep.port == 2)
 200                 return 0;
 201 
 202         return -EINVAL;
 203 }
 204 
 205 static const struct hdmi_codec_ops adv7511_codec_ops = {
 206         .hw_params      = adv7511_hdmi_hw_params,
 207         .audio_shutdown = audio_shutdown,
 208         .audio_startup  = audio_startup,
 209         .get_dai_id     = adv7511_hdmi_i2s_get_dai_id,
 210 };
 211 
 212 static const struct hdmi_codec_pdata codec_data = {
 213         .ops = &adv7511_codec_ops,
 214         .max_i2s_channels = 2,
 215         .i2s = 1,
 216 };
 217 
 218 int adv7511_audio_init(struct device *dev, struct adv7511 *adv7511)
 219 {
 220         adv7511->audio_pdev = platform_device_register_data(dev,
 221                                         HDMI_CODEC_DRV_NAME,
 222                                         PLATFORM_DEVID_AUTO,
 223                                         &codec_data,
 224                                         sizeof(codec_data));
 225         return PTR_ERR_OR_ZERO(adv7511->audio_pdev);
 226 }
 227 
 228 void adv7511_audio_exit(struct adv7511 *adv7511)
 229 {
 230         if (adv7511->audio_pdev) {
 231                 platform_device_unregister(adv7511->audio_pdev);
 232                 adv7511->audio_pdev = NULL;
 233         }
 234 }

/* [<][>][^][v][top][bottom][index][help] */