root/drivers/gpu/drm/msm/hdmi/hdmi_audio.c

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

DEFINITIONS

This source file includes following definitions.
  1. get_arcs
  2. msm_hdmi_audio_update
  3. msm_hdmi_audio_info_setup
  4. msm_hdmi_audio_set_sample_rate

   1 // SPDX-License-Identifier: GPL-2.0-only
   2 /*
   3  * Copyright (C) 2013 Red Hat
   4  * Author: Rob Clark <robdclark@gmail.com>
   5  */
   6 
   7 #include <linux/hdmi.h>
   8 #include "hdmi.h"
   9 
  10 /* maps MSM_HDMI_AUDIO_CHANNEL_n consts used by audio driver to # of channels: */
  11 static int nchannels[] = { 2, 4, 6, 8 };
  12 
  13 /* Supported HDMI Audio sample rates */
  14 #define MSM_HDMI_SAMPLE_RATE_32KHZ              0
  15 #define MSM_HDMI_SAMPLE_RATE_44_1KHZ            1
  16 #define MSM_HDMI_SAMPLE_RATE_48KHZ              2
  17 #define MSM_HDMI_SAMPLE_RATE_88_2KHZ            3
  18 #define MSM_HDMI_SAMPLE_RATE_96KHZ              4
  19 #define MSM_HDMI_SAMPLE_RATE_176_4KHZ           5
  20 #define MSM_HDMI_SAMPLE_RATE_192KHZ             6
  21 #define MSM_HDMI_SAMPLE_RATE_MAX                7
  22 
  23 
  24 struct hdmi_msm_audio_acr {
  25         uint32_t n;     /* N parameter for clock regeneration */
  26         uint32_t cts;   /* CTS parameter for clock regeneration */
  27 };
  28 
  29 struct hdmi_msm_audio_arcs {
  30         unsigned long int pixclock;
  31         struct hdmi_msm_audio_acr lut[MSM_HDMI_SAMPLE_RATE_MAX];
  32 };
  33 
  34 #define HDMI_MSM_AUDIO_ARCS(pclk, ...) { (1000 * (pclk)), __VA_ARGS__ }
  35 
  36 /* Audio constants lookup table for hdmi_msm_audio_acr_setup */
  37 /* Valid Pixel-Clock rates: 25.2MHz, 27MHz, 27.03MHz, 74.25MHz, 148.5MHz */
  38 static const struct hdmi_msm_audio_arcs acr_lut[] = {
  39         /*  25.200MHz  */
  40         HDMI_MSM_AUDIO_ARCS(25200, {
  41                 {4096, 25200}, {6272, 28000}, {6144, 25200}, {12544, 28000},
  42                 {12288, 25200}, {25088, 28000}, {24576, 25200} }),
  43         /*  27.000MHz  */
  44         HDMI_MSM_AUDIO_ARCS(27000, {
  45                 {4096, 27000}, {6272, 30000}, {6144, 27000}, {12544, 30000},
  46                 {12288, 27000}, {25088, 30000}, {24576, 27000} }),
  47         /*  27.027MHz */
  48         HDMI_MSM_AUDIO_ARCS(27030, {
  49                 {4096, 27027}, {6272, 30030}, {6144, 27027}, {12544, 30030},
  50                 {12288, 27027}, {25088, 30030}, {24576, 27027} }),
  51         /*  74.250MHz */
  52         HDMI_MSM_AUDIO_ARCS(74250, {
  53                 {4096, 74250}, {6272, 82500}, {6144, 74250}, {12544, 82500},
  54                 {12288, 74250}, {25088, 82500}, {24576, 74250} }),
  55         /* 148.500MHz */
  56         HDMI_MSM_AUDIO_ARCS(148500, {
  57                 {4096, 148500}, {6272, 165000}, {6144, 148500}, {12544, 165000},
  58                 {12288, 148500}, {25088, 165000}, {24576, 148500} }),
  59 };
  60 
  61 static const struct hdmi_msm_audio_arcs *get_arcs(unsigned long int pixclock)
  62 {
  63         int i;
  64 
  65         for (i = 0; i < ARRAY_SIZE(acr_lut); i++) {
  66                 const struct hdmi_msm_audio_arcs *arcs = &acr_lut[i];
  67                 if (arcs->pixclock == pixclock)
  68                         return arcs;
  69         }
  70 
  71         return NULL;
  72 }
  73 
  74 int msm_hdmi_audio_update(struct hdmi *hdmi)
  75 {
  76         struct hdmi_audio *audio = &hdmi->audio;
  77         struct hdmi_audio_infoframe *info = &audio->infoframe;
  78         const struct hdmi_msm_audio_arcs *arcs = NULL;
  79         bool enabled = audio->enabled;
  80         uint32_t acr_pkt_ctrl, vbi_pkt_ctrl, aud_pkt_ctrl;
  81         uint32_t infofrm_ctrl, audio_config;
  82 
  83         DBG("audio: enabled=%d, channels=%d, channel_allocation=0x%x, "
  84                 "level_shift_value=%d, downmix_inhibit=%d, rate=%d",
  85                 audio->enabled, info->channels,  info->channel_allocation,
  86                 info->level_shift_value, info->downmix_inhibit, audio->rate);
  87         DBG("video: power_on=%d, pixclock=%lu", hdmi->power_on, hdmi->pixclock);
  88 
  89         if (enabled && !(hdmi->power_on && hdmi->pixclock)) {
  90                 DBG("disabling audio: no video");
  91                 enabled = false;
  92         }
  93 
  94         if (enabled) {
  95                 arcs = get_arcs(hdmi->pixclock);
  96                 if (!arcs) {
  97                         DBG("disabling audio: unsupported pixclock: %lu",
  98                                         hdmi->pixclock);
  99                         enabled = false;
 100                 }
 101         }
 102 
 103         /* Read first before writing */
 104         acr_pkt_ctrl = hdmi_read(hdmi, REG_HDMI_ACR_PKT_CTRL);
 105         vbi_pkt_ctrl = hdmi_read(hdmi, REG_HDMI_VBI_PKT_CTRL);
 106         aud_pkt_ctrl = hdmi_read(hdmi, REG_HDMI_AUDIO_PKT_CTRL1);
 107         infofrm_ctrl = hdmi_read(hdmi, REG_HDMI_INFOFRAME_CTRL0);
 108         audio_config = hdmi_read(hdmi, REG_HDMI_AUDIO_CFG);
 109 
 110         /* Clear N/CTS selection bits */
 111         acr_pkt_ctrl &= ~HDMI_ACR_PKT_CTRL_SELECT__MASK;
 112 
 113         if (enabled) {
 114                 uint32_t n, cts, multiplier;
 115                 enum hdmi_acr_cts select;
 116                 uint8_t buf[14];
 117 
 118                 n   = arcs->lut[audio->rate].n;
 119                 cts = arcs->lut[audio->rate].cts;
 120 
 121                 if ((MSM_HDMI_SAMPLE_RATE_192KHZ == audio->rate) ||
 122                                 (MSM_HDMI_SAMPLE_RATE_176_4KHZ == audio->rate)) {
 123                         multiplier = 4;
 124                         n >>= 2; /* divide N by 4 and use multiplier */
 125                 } else if ((MSM_HDMI_SAMPLE_RATE_96KHZ == audio->rate) ||
 126                                 (MSM_HDMI_SAMPLE_RATE_88_2KHZ == audio->rate)) {
 127                         multiplier = 2;
 128                         n >>= 1; /* divide N by 2 and use multiplier */
 129                 } else {
 130                         multiplier = 1;
 131                 }
 132 
 133                 DBG("n=%u, cts=%u, multiplier=%u", n, cts, multiplier);
 134 
 135                 acr_pkt_ctrl |= HDMI_ACR_PKT_CTRL_SOURCE;
 136                 acr_pkt_ctrl |= HDMI_ACR_PKT_CTRL_AUDIO_PRIORITY;
 137                 acr_pkt_ctrl |= HDMI_ACR_PKT_CTRL_N_MULTIPLIER(multiplier);
 138 
 139                 if ((MSM_HDMI_SAMPLE_RATE_48KHZ == audio->rate) ||
 140                                 (MSM_HDMI_SAMPLE_RATE_96KHZ == audio->rate) ||
 141                                 (MSM_HDMI_SAMPLE_RATE_192KHZ == audio->rate))
 142                         select = ACR_48;
 143                 else if ((MSM_HDMI_SAMPLE_RATE_44_1KHZ == audio->rate) ||
 144                                 (MSM_HDMI_SAMPLE_RATE_88_2KHZ == audio->rate) ||
 145                                 (MSM_HDMI_SAMPLE_RATE_176_4KHZ == audio->rate))
 146                         select = ACR_44;
 147                 else /* default to 32k */
 148                         select = ACR_32;
 149 
 150                 acr_pkt_ctrl |= HDMI_ACR_PKT_CTRL_SELECT(select);
 151 
 152                 hdmi_write(hdmi, REG_HDMI_ACR_0(select - 1),
 153                                 HDMI_ACR_0_CTS(cts));
 154                 hdmi_write(hdmi, REG_HDMI_ACR_1(select - 1),
 155                                 HDMI_ACR_1_N(n));
 156 
 157                 hdmi_write(hdmi, REG_HDMI_AUDIO_PKT_CTRL2,
 158                                 COND(info->channels != 2, HDMI_AUDIO_PKT_CTRL2_LAYOUT) |
 159                                 HDMI_AUDIO_PKT_CTRL2_OVERRIDE);
 160 
 161                 acr_pkt_ctrl |= HDMI_ACR_PKT_CTRL_CONT;
 162                 acr_pkt_ctrl |= HDMI_ACR_PKT_CTRL_SEND;
 163 
 164                 /* configure infoframe: */
 165                 hdmi_audio_infoframe_pack(info, buf, sizeof(buf));
 166                 hdmi_write(hdmi, REG_HDMI_AUDIO_INFO0,
 167                                 (buf[3] <<  0) | (buf[4] <<  8) |
 168                                 (buf[5] << 16) | (buf[6] << 24));
 169                 hdmi_write(hdmi, REG_HDMI_AUDIO_INFO1,
 170                                 (buf[7] <<  0) | (buf[8] << 8));
 171 
 172                 hdmi_write(hdmi, REG_HDMI_GC, 0);
 173 
 174                 vbi_pkt_ctrl |= HDMI_VBI_PKT_CTRL_GC_ENABLE;
 175                 vbi_pkt_ctrl |= HDMI_VBI_PKT_CTRL_GC_EVERY_FRAME;
 176 
 177                 aud_pkt_ctrl |= HDMI_AUDIO_PKT_CTRL1_AUDIO_SAMPLE_SEND;
 178 
 179                 infofrm_ctrl |= HDMI_INFOFRAME_CTRL0_AUDIO_INFO_SEND;
 180                 infofrm_ctrl |= HDMI_INFOFRAME_CTRL0_AUDIO_INFO_CONT;
 181                 infofrm_ctrl |= HDMI_INFOFRAME_CTRL0_AUDIO_INFO_SOURCE;
 182                 infofrm_ctrl |= HDMI_INFOFRAME_CTRL0_AUDIO_INFO_UPDATE;
 183 
 184                 audio_config &= ~HDMI_AUDIO_CFG_FIFO_WATERMARK__MASK;
 185                 audio_config |= HDMI_AUDIO_CFG_FIFO_WATERMARK(4);
 186                 audio_config |= HDMI_AUDIO_CFG_ENGINE_ENABLE;
 187         } else {
 188                 acr_pkt_ctrl &= ~HDMI_ACR_PKT_CTRL_CONT;
 189                 acr_pkt_ctrl &= ~HDMI_ACR_PKT_CTRL_SEND;
 190                 vbi_pkt_ctrl &= ~HDMI_VBI_PKT_CTRL_GC_ENABLE;
 191                 vbi_pkt_ctrl &= ~HDMI_VBI_PKT_CTRL_GC_EVERY_FRAME;
 192                 aud_pkt_ctrl &= ~HDMI_AUDIO_PKT_CTRL1_AUDIO_SAMPLE_SEND;
 193                 infofrm_ctrl &= ~HDMI_INFOFRAME_CTRL0_AUDIO_INFO_SEND;
 194                 infofrm_ctrl &= ~HDMI_INFOFRAME_CTRL0_AUDIO_INFO_CONT;
 195                 infofrm_ctrl &= ~HDMI_INFOFRAME_CTRL0_AUDIO_INFO_SOURCE;
 196                 infofrm_ctrl &= ~HDMI_INFOFRAME_CTRL0_AUDIO_INFO_UPDATE;
 197                 audio_config &= ~HDMI_AUDIO_CFG_ENGINE_ENABLE;
 198         }
 199 
 200         hdmi_write(hdmi, REG_HDMI_ACR_PKT_CTRL, acr_pkt_ctrl);
 201         hdmi_write(hdmi, REG_HDMI_VBI_PKT_CTRL, vbi_pkt_ctrl);
 202         hdmi_write(hdmi, REG_HDMI_AUDIO_PKT_CTRL1, aud_pkt_ctrl);
 203         hdmi_write(hdmi, REG_HDMI_INFOFRAME_CTRL0, infofrm_ctrl);
 204 
 205         hdmi_write(hdmi, REG_HDMI_AUD_INT,
 206                         COND(enabled, HDMI_AUD_INT_AUD_FIFO_URUN_INT) |
 207                         COND(enabled, HDMI_AUD_INT_AUD_SAM_DROP_INT));
 208 
 209         hdmi_write(hdmi, REG_HDMI_AUDIO_CFG, audio_config);
 210 
 211 
 212         DBG("audio %sabled", enabled ? "en" : "dis");
 213 
 214         return 0;
 215 }
 216 
 217 int msm_hdmi_audio_info_setup(struct hdmi *hdmi, bool enabled,
 218         uint32_t num_of_channels, uint32_t channel_allocation,
 219         uint32_t level_shift, bool down_mix)
 220 {
 221         struct hdmi_audio *audio;
 222 
 223         if (!hdmi)
 224                 return -ENXIO;
 225 
 226         audio = &hdmi->audio;
 227 
 228         if (num_of_channels >= ARRAY_SIZE(nchannels))
 229                 return -EINVAL;
 230 
 231         audio->enabled = enabled;
 232         audio->infoframe.channels = nchannels[num_of_channels];
 233         audio->infoframe.channel_allocation = channel_allocation;
 234         audio->infoframe.level_shift_value = level_shift;
 235         audio->infoframe.downmix_inhibit = down_mix;
 236 
 237         return msm_hdmi_audio_update(hdmi);
 238 }
 239 
 240 void msm_hdmi_audio_set_sample_rate(struct hdmi *hdmi, int rate)
 241 {
 242         struct hdmi_audio *audio;
 243 
 244         if (!hdmi)
 245                 return;
 246 
 247         audio = &hdmi->audio;
 248 
 249         if ((rate < 0) || (rate >= MSM_HDMI_SAMPLE_RATE_MAX))
 250                 return;
 251 
 252         audio->rate = rate;
 253         msm_hdmi_audio_update(hdmi);
 254 }

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