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