1110 lines · c
1// SPDX-License-Identifier: GPL-2.0-only2/*3 * ALSA SoC codec for HDMI encoder drivers4 * Copyright (C) 2015 Texas Instruments Incorporated - https://www.ti.com/5 * Author: Jyri Sarha <jsarha@ti.com>6 */7#include <linux/module.h>8#include <linux/string.h>9#include <sound/core.h>10#include <sound/jack.h>11#include <sound/pcm.h>12#include <sound/pcm_params.h>13#include <sound/soc.h>14#include <sound/tlv.h>15#include <sound/pcm_drm_eld.h>16#include <sound/hdmi-codec.h>17#include <sound/pcm_iec958.h>18 19#include <drm/drm_crtc.h> /* This is only to get MAX_ELD_BYTES */20#include <drm/drm_eld.h>21 22#define HDMI_CODEC_CHMAP_IDX_UNKNOWN -123 24/*25 * CEA speaker placement for HDMI 1.4:26 *27 * FL FLC FC FRC FR FRW28 *29 * LFE30 *31 * RL RLC RC RRC RR32 *33 * Speaker placement has to be extended to support HDMI 2.034 */35enum hdmi_codec_cea_spk_placement {36 FL = BIT(0), /* Front Left */37 FC = BIT(1), /* Front Center */38 FR = BIT(2), /* Front Right */39 FLC = BIT(3), /* Front Left Center */40 FRC = BIT(4), /* Front Right Center */41 RL = BIT(5), /* Rear Left */42 RC = BIT(6), /* Rear Center */43 RR = BIT(7), /* Rear Right */44 RLC = BIT(8), /* Rear Left Center */45 RRC = BIT(9), /* Rear Right Center */46 LFE = BIT(10), /* Low Frequency Effect */47};48 49/*50 * cea Speaker allocation structure51 */52struct hdmi_codec_cea_spk_alloc {53 const int ca_id;54 unsigned int n_ch;55 unsigned long mask;56};57 58/* Channel maps stereo HDMI */59static const struct snd_pcm_chmap_elem hdmi_codec_stereo_chmaps[] = {60 { .channels = 2,61 .map = { SNDRV_CHMAP_FL, SNDRV_CHMAP_FR } },62 { }63};64 65/* Channel maps for multi-channel playbacks, up to 8 n_ch */66static const struct snd_pcm_chmap_elem hdmi_codec_8ch_chmaps[] = {67 { .channels = 2, /* CA_ID 0x00 */68 .map = { SNDRV_CHMAP_FL, SNDRV_CHMAP_FR } },69 { .channels = 4, /* CA_ID 0x01 */70 .map = { SNDRV_CHMAP_FL, SNDRV_CHMAP_FR, SNDRV_CHMAP_LFE,71 SNDRV_CHMAP_NA } },72 { .channels = 4, /* CA_ID 0x02 */73 .map = { SNDRV_CHMAP_FL, SNDRV_CHMAP_FR, SNDRV_CHMAP_NA,74 SNDRV_CHMAP_FC } },75 { .channels = 4, /* CA_ID 0x03 */76 .map = { SNDRV_CHMAP_FL, SNDRV_CHMAP_FR, SNDRV_CHMAP_LFE,77 SNDRV_CHMAP_FC } },78 { .channels = 6, /* CA_ID 0x04 */79 .map = { SNDRV_CHMAP_FL, SNDRV_CHMAP_FR, SNDRV_CHMAP_NA,80 SNDRV_CHMAP_NA, SNDRV_CHMAP_RC, SNDRV_CHMAP_NA } },81 { .channels = 6, /* CA_ID 0x05 */82 .map = { SNDRV_CHMAP_FL, SNDRV_CHMAP_FR, SNDRV_CHMAP_LFE,83 SNDRV_CHMAP_NA, SNDRV_CHMAP_RC, SNDRV_CHMAP_NA } },84 { .channels = 6, /* CA_ID 0x06 */85 .map = { SNDRV_CHMAP_FL, SNDRV_CHMAP_FR, SNDRV_CHMAP_NA,86 SNDRV_CHMAP_FC, SNDRV_CHMAP_RC, SNDRV_CHMAP_NA } },87 { .channels = 6, /* CA_ID 0x07 */88 .map = { SNDRV_CHMAP_FL, SNDRV_CHMAP_FR, SNDRV_CHMAP_LFE,89 SNDRV_CHMAP_FC, SNDRV_CHMAP_RC, SNDRV_CHMAP_NA } },90 { .channels = 6, /* CA_ID 0x08 */91 .map = { SNDRV_CHMAP_FL, SNDRV_CHMAP_FR, SNDRV_CHMAP_NA,92 SNDRV_CHMAP_NA, SNDRV_CHMAP_RL, SNDRV_CHMAP_RR } },93 { .channels = 6, /* CA_ID 0x09 */94 .map = { SNDRV_CHMAP_FL, SNDRV_CHMAP_FR, SNDRV_CHMAP_LFE,95 SNDRV_CHMAP_NA, SNDRV_CHMAP_RL, SNDRV_CHMAP_RR } },96 { .channels = 6, /* CA_ID 0x0A */97 .map = { SNDRV_CHMAP_FL, SNDRV_CHMAP_FR, SNDRV_CHMAP_NA,98 SNDRV_CHMAP_FC, SNDRV_CHMAP_RL, SNDRV_CHMAP_RR } },99 { .channels = 6, /* CA_ID 0x0B */100 .map = { SNDRV_CHMAP_FL, SNDRV_CHMAP_FR, SNDRV_CHMAP_LFE,101 SNDRV_CHMAP_FC, SNDRV_CHMAP_RL, SNDRV_CHMAP_RR } },102 { .channels = 8, /* CA_ID 0x0C */103 .map = { SNDRV_CHMAP_FL, SNDRV_CHMAP_FR, SNDRV_CHMAP_NA,104 SNDRV_CHMAP_NA, SNDRV_CHMAP_RL, SNDRV_CHMAP_RR,105 SNDRV_CHMAP_RC, SNDRV_CHMAP_NA } },106 { .channels = 8, /* CA_ID 0x0D */107 .map = { SNDRV_CHMAP_FL, SNDRV_CHMAP_FR, SNDRV_CHMAP_LFE,108 SNDRV_CHMAP_NA, SNDRV_CHMAP_RL, SNDRV_CHMAP_RR,109 SNDRV_CHMAP_RC, SNDRV_CHMAP_NA } },110 { .channels = 8, /* CA_ID 0x0E */111 .map = { SNDRV_CHMAP_FL, SNDRV_CHMAP_FR, SNDRV_CHMAP_NA,112 SNDRV_CHMAP_FC, SNDRV_CHMAP_RL, SNDRV_CHMAP_RR,113 SNDRV_CHMAP_RC, SNDRV_CHMAP_NA } },114 { .channels = 8, /* CA_ID 0x0F */115 .map = { SNDRV_CHMAP_FL, SNDRV_CHMAP_FR, SNDRV_CHMAP_LFE,116 SNDRV_CHMAP_FC, SNDRV_CHMAP_RL, SNDRV_CHMAP_RR,117 SNDRV_CHMAP_RC, SNDRV_CHMAP_NA } },118 { .channels = 8, /* CA_ID 0x10 */119 .map = { SNDRV_CHMAP_FL, SNDRV_CHMAP_FR, SNDRV_CHMAP_NA,120 SNDRV_CHMAP_NA, SNDRV_CHMAP_RL, SNDRV_CHMAP_RR,121 SNDRV_CHMAP_RLC, SNDRV_CHMAP_RRC } },122 { .channels = 8, /* CA_ID 0x11 */123 .map = { SNDRV_CHMAP_FL, SNDRV_CHMAP_FR, SNDRV_CHMAP_LFE,124 SNDRV_CHMAP_NA, SNDRV_CHMAP_RL, SNDRV_CHMAP_RR,125 SNDRV_CHMAP_RLC, SNDRV_CHMAP_RRC } },126 { .channels = 8, /* CA_ID 0x12 */127 .map = { SNDRV_CHMAP_FL, SNDRV_CHMAP_FR, SNDRV_CHMAP_NA,128 SNDRV_CHMAP_FC, SNDRV_CHMAP_RL, SNDRV_CHMAP_RR,129 SNDRV_CHMAP_RLC, SNDRV_CHMAP_RRC } },130 { .channels = 8, /* CA_ID 0x13 */131 .map = { SNDRV_CHMAP_FL, SNDRV_CHMAP_FR, SNDRV_CHMAP_LFE,132 SNDRV_CHMAP_FC, SNDRV_CHMAP_RL, SNDRV_CHMAP_RR,133 SNDRV_CHMAP_RLC, SNDRV_CHMAP_RRC } },134 { .channels = 8, /* CA_ID 0x14 */135 .map = { SNDRV_CHMAP_FL, SNDRV_CHMAP_FR, SNDRV_CHMAP_NA,136 SNDRV_CHMAP_NA, SNDRV_CHMAP_NA, SNDRV_CHMAP_NA,137 SNDRV_CHMAP_FLC, SNDRV_CHMAP_FRC } },138 { .channels = 8, /* CA_ID 0x15 */139 .map = { SNDRV_CHMAP_FL, SNDRV_CHMAP_FR, SNDRV_CHMAP_LFE,140 SNDRV_CHMAP_NA, SNDRV_CHMAP_NA, SNDRV_CHMAP_NA,141 SNDRV_CHMAP_FLC, SNDRV_CHMAP_FRC } },142 { .channels = 8, /* CA_ID 0x16 */143 .map = { SNDRV_CHMAP_FL, SNDRV_CHMAP_FR, SNDRV_CHMAP_NA,144 SNDRV_CHMAP_FC, SNDRV_CHMAP_NA, SNDRV_CHMAP_NA,145 SNDRV_CHMAP_FLC, SNDRV_CHMAP_FRC } },146 { .channels = 8, /* CA_ID 0x17 */147 .map = { SNDRV_CHMAP_FL, SNDRV_CHMAP_FR, SNDRV_CHMAP_LFE,148 SNDRV_CHMAP_FC, SNDRV_CHMAP_NA, SNDRV_CHMAP_NA,149 SNDRV_CHMAP_FLC, SNDRV_CHMAP_FRC } },150 { .channels = 8, /* CA_ID 0x18 */151 .map = { SNDRV_CHMAP_FL, SNDRV_CHMAP_FR, SNDRV_CHMAP_NA,152 SNDRV_CHMAP_NA, SNDRV_CHMAP_NA, SNDRV_CHMAP_NA,153 SNDRV_CHMAP_FLC, SNDRV_CHMAP_FRC } },154 { .channels = 8, /* CA_ID 0x19 */155 .map = { SNDRV_CHMAP_FL, SNDRV_CHMAP_FR, SNDRV_CHMAP_LFE,156 SNDRV_CHMAP_NA, SNDRV_CHMAP_NA, SNDRV_CHMAP_NA,157 SNDRV_CHMAP_FLC, SNDRV_CHMAP_FRC } },158 { .channels = 8, /* CA_ID 0x1A */159 .map = { SNDRV_CHMAP_FL, SNDRV_CHMAP_FR, SNDRV_CHMAP_NA,160 SNDRV_CHMAP_FC, SNDRV_CHMAP_NA, SNDRV_CHMAP_NA,161 SNDRV_CHMAP_FLC, SNDRV_CHMAP_FRC } },162 { .channels = 8, /* CA_ID 0x1B */163 .map = { SNDRV_CHMAP_FL, SNDRV_CHMAP_FR, SNDRV_CHMAP_LFE,164 SNDRV_CHMAP_FC, SNDRV_CHMAP_NA, SNDRV_CHMAP_NA,165 SNDRV_CHMAP_FLC, SNDRV_CHMAP_FRC } },166 { .channels = 8, /* CA_ID 0x1C */167 .map = { SNDRV_CHMAP_FL, SNDRV_CHMAP_FR, SNDRV_CHMAP_NA,168 SNDRV_CHMAP_NA, SNDRV_CHMAP_NA, SNDRV_CHMAP_NA,169 SNDRV_CHMAP_FLC, SNDRV_CHMAP_FRC } },170 { .channels = 8, /* CA_ID 0x1D */171 .map = { SNDRV_CHMAP_FL, SNDRV_CHMAP_FR, SNDRV_CHMAP_LFE,172 SNDRV_CHMAP_NA, SNDRV_CHMAP_NA, SNDRV_CHMAP_NA,173 SNDRV_CHMAP_FLC, SNDRV_CHMAP_FRC } },174 { .channels = 8, /* CA_ID 0x1E */175 .map = { SNDRV_CHMAP_FL, SNDRV_CHMAP_FR, SNDRV_CHMAP_NA,176 SNDRV_CHMAP_FC, SNDRV_CHMAP_NA, SNDRV_CHMAP_NA,177 SNDRV_CHMAP_FLC, SNDRV_CHMAP_FRC } },178 { .channels = 8, /* CA_ID 0x1F */179 .map = { SNDRV_CHMAP_FL, SNDRV_CHMAP_FR, SNDRV_CHMAP_LFE,180 SNDRV_CHMAP_FC, SNDRV_CHMAP_NA, SNDRV_CHMAP_NA,181 SNDRV_CHMAP_FLC, SNDRV_CHMAP_FRC } },182 { }183};184 185/*186 * hdmi_codec_channel_alloc: speaker configuration available for CEA187 *188 * This is an ordered list that must match with hdmi_codec_8ch_chmaps struct189 * The preceding ones have better chances to be selected by190 * hdmi_codec_get_ch_alloc_table_idx().191 */192static const struct hdmi_codec_cea_spk_alloc hdmi_codec_channel_alloc[] = {193 { .ca_id = 0x00, .n_ch = 2,194 .mask = FL | FR},195 /* 2.1 */196 { .ca_id = 0x01, .n_ch = 4,197 .mask = FL | FR | LFE},198 /* Dolby Surround */199 { .ca_id = 0x02, .n_ch = 4,200 .mask = FL | FR | FC },201 /* surround51 */202 { .ca_id = 0x0b, .n_ch = 6,203 .mask = FL | FR | LFE | FC | RL | RR},204 /* surround40 */205 { .ca_id = 0x08, .n_ch = 6,206 .mask = FL | FR | RL | RR },207 /* surround41 */208 { .ca_id = 0x09, .n_ch = 6,209 .mask = FL | FR | LFE | RL | RR },210 /* surround50 */211 { .ca_id = 0x0a, .n_ch = 6,212 .mask = FL | FR | FC | RL | RR },213 /* 6.1 */214 { .ca_id = 0x0f, .n_ch = 8,215 .mask = FL | FR | LFE | FC | RL | RR | RC },216 /* surround71 */217 { .ca_id = 0x13, .n_ch = 8,218 .mask = FL | FR | LFE | FC | RL | RR | RLC | RRC },219 /* others */220 { .ca_id = 0x03, .n_ch = 8,221 .mask = FL | FR | LFE | FC },222 { .ca_id = 0x04, .n_ch = 8,223 .mask = FL | FR | RC},224 { .ca_id = 0x05, .n_ch = 8,225 .mask = FL | FR | LFE | RC },226 { .ca_id = 0x06, .n_ch = 8,227 .mask = FL | FR | FC | RC },228 { .ca_id = 0x07, .n_ch = 8,229 .mask = FL | FR | LFE | FC | RC },230 { .ca_id = 0x0c, .n_ch = 8,231 .mask = FL | FR | RC | RL | RR },232 { .ca_id = 0x0d, .n_ch = 8,233 .mask = FL | FR | LFE | RL | RR | RC },234 { .ca_id = 0x0e, .n_ch = 8,235 .mask = FL | FR | FC | RL | RR | RC },236 { .ca_id = 0x10, .n_ch = 8,237 .mask = FL | FR | RL | RR | RLC | RRC },238 { .ca_id = 0x11, .n_ch = 8,239 .mask = FL | FR | LFE | RL | RR | RLC | RRC },240 { .ca_id = 0x12, .n_ch = 8,241 .mask = FL | FR | FC | RL | RR | RLC | RRC },242 { .ca_id = 0x14, .n_ch = 8,243 .mask = FL | FR | FLC | FRC },244 { .ca_id = 0x15, .n_ch = 8,245 .mask = FL | FR | LFE | FLC | FRC },246 { .ca_id = 0x16, .n_ch = 8,247 .mask = FL | FR | FC | FLC | FRC },248 { .ca_id = 0x17, .n_ch = 8,249 .mask = FL | FR | LFE | FC | FLC | FRC },250 { .ca_id = 0x18, .n_ch = 8,251 .mask = FL | FR | RC | FLC | FRC },252 { .ca_id = 0x19, .n_ch = 8,253 .mask = FL | FR | LFE | RC | FLC | FRC },254 { .ca_id = 0x1a, .n_ch = 8,255 .mask = FL | FR | RC | FC | FLC | FRC },256 { .ca_id = 0x1b, .n_ch = 8,257 .mask = FL | FR | LFE | RC | FC | FLC | FRC },258 { .ca_id = 0x1c, .n_ch = 8,259 .mask = FL | FR | RL | RR | FLC | FRC },260 { .ca_id = 0x1d, .n_ch = 8,261 .mask = FL | FR | LFE | RL | RR | FLC | FRC },262 { .ca_id = 0x1e, .n_ch = 8,263 .mask = FL | FR | FC | RL | RR | FLC | FRC },264 { .ca_id = 0x1f, .n_ch = 8,265 .mask = FL | FR | LFE | FC | RL | RR | FLC | FRC },266};267 268struct hdmi_codec_priv {269 struct hdmi_codec_pdata hcd;270 uint8_t eld[MAX_ELD_BYTES];271 struct snd_pcm_chmap *chmap_info;272 unsigned int chmap_idx;273 struct mutex lock;274 bool busy;275 struct snd_soc_jack *jack;276 unsigned int jack_status;277 u8 iec_status[AES_IEC958_STATUS_SIZE];278};279 280static const struct snd_soc_dapm_widget hdmi_widgets[] = {281 SND_SOC_DAPM_OUTPUT("TX"),282 SND_SOC_DAPM_OUTPUT("RX"),283};284 285enum {286 DAI_ID_I2S = 0,287 DAI_ID_SPDIF,288};289 290static int hdmi_eld_ctl_info(struct snd_kcontrol *kcontrol,291 struct snd_ctl_elem_info *uinfo)292{293 uinfo->type = SNDRV_CTL_ELEM_TYPE_BYTES;294 uinfo->count = sizeof_field(struct hdmi_codec_priv, eld);295 296 return 0;297}298 299static int hdmi_eld_ctl_get(struct snd_kcontrol *kcontrol,300 struct snd_ctl_elem_value *ucontrol)301{302 struct snd_soc_component *component = snd_kcontrol_chip(kcontrol);303 struct hdmi_codec_priv *hcp = snd_soc_component_get_drvdata(component);304 305 memcpy(ucontrol->value.bytes.data, hcp->eld, sizeof(hcp->eld));306 307 return 0;308}309 310static unsigned long hdmi_codec_spk_mask_from_alloc(int spk_alloc)311{312 int i;313 static const unsigned long hdmi_codec_eld_spk_alloc_bits[] = {314 [0] = FL | FR, [1] = LFE, [2] = FC, [3] = RL | RR,315 [4] = RC, [5] = FLC | FRC, [6] = RLC | RRC,316 };317 unsigned long spk_mask = 0;318 319 for (i = 0; i < ARRAY_SIZE(hdmi_codec_eld_spk_alloc_bits); i++) {320 if (spk_alloc & (1 << i))321 spk_mask |= hdmi_codec_eld_spk_alloc_bits[i];322 }323 324 return spk_mask;325}326 327static void hdmi_codec_eld_chmap(struct hdmi_codec_priv *hcp)328{329 u8 spk_alloc;330 unsigned long spk_mask;331 332 spk_alloc = drm_eld_get_spk_alloc(hcp->eld);333 spk_mask = hdmi_codec_spk_mask_from_alloc(spk_alloc);334 335 /* Detect if only stereo supported, else return 8 channels mappings */336 if ((spk_mask & ~(FL | FR)) && hcp->chmap_info->max_channels > 2)337 hcp->chmap_info->chmap = hdmi_codec_8ch_chmaps;338 else339 hcp->chmap_info->chmap = hdmi_codec_stereo_chmaps;340}341 342static int hdmi_codec_get_ch_alloc_table_idx(struct hdmi_codec_priv *hcp,343 unsigned char channels)344{345 int i;346 u8 spk_alloc;347 unsigned long spk_mask;348 const struct hdmi_codec_cea_spk_alloc *cap = hdmi_codec_channel_alloc;349 350 spk_alloc = drm_eld_get_spk_alloc(hcp->eld);351 spk_mask = hdmi_codec_spk_mask_from_alloc(spk_alloc);352 353 for (i = 0; i < ARRAY_SIZE(hdmi_codec_channel_alloc); i++, cap++) {354 /* If spk_alloc == 0, HDMI is unplugged return stereo config*/355 if (!spk_alloc && cap->ca_id == 0)356 return i;357 if (cap->n_ch != channels)358 continue;359 if (!(cap->mask == (spk_mask & cap->mask)))360 continue;361 return i;362 }363 364 return -EINVAL;365}366static int hdmi_codec_chmap_ctl_get(struct snd_kcontrol *kcontrol,367 struct snd_ctl_elem_value *ucontrol)368{369 unsigned const char *map;370 unsigned int i;371 struct snd_pcm_chmap *info = snd_kcontrol_chip(kcontrol);372 struct hdmi_codec_priv *hcp = info->private_data;373 374 map = info->chmap[hcp->chmap_idx].map;375 376 for (i = 0; i < info->max_channels; i++) {377 if (hcp->chmap_idx == HDMI_CODEC_CHMAP_IDX_UNKNOWN)378 ucontrol->value.integer.value[i] = 0;379 else380 ucontrol->value.integer.value[i] = map[i];381 }382 383 return 0;384}385 386static int hdmi_codec_iec958_info(struct snd_kcontrol *kcontrol,387 struct snd_ctl_elem_info *uinfo)388{389 uinfo->type = SNDRV_CTL_ELEM_TYPE_IEC958;390 uinfo->count = 1;391 return 0;392}393 394static int hdmi_codec_iec958_default_get(struct snd_kcontrol *kcontrol,395 struct snd_ctl_elem_value *ucontrol)396{397 struct snd_soc_component *component = snd_kcontrol_chip(kcontrol);398 struct hdmi_codec_priv *hcp = snd_soc_component_get_drvdata(component);399 400 memcpy(ucontrol->value.iec958.status, hcp->iec_status,401 sizeof(hcp->iec_status));402 403 return 0;404}405 406static int hdmi_codec_iec958_default_put(struct snd_kcontrol *kcontrol,407 struct snd_ctl_elem_value *ucontrol)408{409 struct snd_soc_component *component = snd_kcontrol_chip(kcontrol);410 struct hdmi_codec_priv *hcp = snd_soc_component_get_drvdata(component);411 412 memcpy(hcp->iec_status, ucontrol->value.iec958.status,413 sizeof(hcp->iec_status));414 415 return 0;416}417 418static int hdmi_codec_iec958_mask_get(struct snd_kcontrol *kcontrol,419 struct snd_ctl_elem_value *ucontrol)420{421 memset(ucontrol->value.iec958.status, 0xff,422 sizeof_field(struct hdmi_codec_priv, iec_status));423 424 return 0;425}426 427static int hdmi_codec_startup(struct snd_pcm_substream *substream,428 struct snd_soc_dai *dai)429{430 struct hdmi_codec_priv *hcp = snd_soc_dai_get_drvdata(dai);431 bool tx = substream->stream == SNDRV_PCM_STREAM_PLAYBACK;432 bool has_capture = !hcp->hcd.no_i2s_capture;433 bool has_playback = !hcp->hcd.no_i2s_playback;434 int ret = 0;435 436 if (!((has_playback && tx) || (has_capture && !tx)))437 return 0;438 439 mutex_lock(&hcp->lock);440 if (hcp->busy) {441 dev_err(dai->dev, "Only one simultaneous stream supported!\n");442 mutex_unlock(&hcp->lock);443 return -EINVAL;444 }445 446 if (hcp->hcd.ops->audio_startup) {447 ret = hcp->hcd.ops->audio_startup(dai->dev->parent, hcp->hcd.data);448 if (ret)449 goto err;450 }451 452 if (tx && hcp->hcd.ops->get_eld) {453 ret = hcp->hcd.ops->get_eld(dai->dev->parent, hcp->hcd.data,454 hcp->eld, sizeof(hcp->eld));455 if (ret)456 goto err;457 458 ret = snd_pcm_hw_constraint_eld(substream->runtime, hcp->eld);459 if (ret)460 goto err;461 462 /* Select chmap supported */463 hdmi_codec_eld_chmap(hcp);464 }465 466 hcp->busy = true;467 468err:469 mutex_unlock(&hcp->lock);470 return ret;471}472 473static void hdmi_codec_shutdown(struct snd_pcm_substream *substream,474 struct snd_soc_dai *dai)475{476 struct hdmi_codec_priv *hcp = snd_soc_dai_get_drvdata(dai);477 bool tx = substream->stream == SNDRV_PCM_STREAM_PLAYBACK;478 bool has_capture = !hcp->hcd.no_i2s_capture;479 bool has_playback = !hcp->hcd.no_i2s_playback;480 481 if (!((has_playback && tx) || (has_capture && !tx)))482 return;483 484 hcp->chmap_idx = HDMI_CODEC_CHMAP_IDX_UNKNOWN;485 hcp->hcd.ops->audio_shutdown(dai->dev->parent, hcp->hcd.data);486 487 mutex_lock(&hcp->lock);488 hcp->busy = false;489 mutex_unlock(&hcp->lock);490}491 492static int hdmi_codec_fill_codec_params(struct snd_soc_dai *dai,493 unsigned int sample_width,494 unsigned int sample_rate,495 unsigned int channels,496 struct hdmi_codec_params *hp)497{498 struct hdmi_codec_priv *hcp = snd_soc_dai_get_drvdata(dai);499 int idx = HDMI_CODEC_CHMAP_IDX_UNKNOWN;500 u8 ca_id = 0;501 bool pcm_audio = !(hcp->iec_status[0] & IEC958_AES0_NONAUDIO);502 503 if (pcm_audio) {504 /* Select a channel allocation that matches with ELD and pcm channels */505 idx = hdmi_codec_get_ch_alloc_table_idx(hcp, channels);506 507 if (idx < 0) {508 dev_err(dai->dev, "Not able to map channels to speakers (%d)\n",509 idx);510 hcp->chmap_idx = HDMI_CODEC_CHMAP_IDX_UNKNOWN;511 return idx;512 }513 514 ca_id = hdmi_codec_channel_alloc[idx].ca_id;515 }516 517 memset(hp, 0, sizeof(*hp));518 519 hdmi_audio_infoframe_init(&hp->cea);520 521 if (pcm_audio)522 hp->cea.channels = channels;523 else524 hp->cea.channels = 0;525 526 hp->cea.coding_type = HDMI_AUDIO_CODING_TYPE_STREAM;527 hp->cea.sample_size = HDMI_AUDIO_SAMPLE_SIZE_STREAM;528 hp->cea.sample_frequency = HDMI_AUDIO_SAMPLE_FREQUENCY_STREAM;529 hp->cea.channel_allocation = ca_id;530 531 hp->sample_width = sample_width;532 hp->sample_rate = sample_rate;533 hp->channels = channels;534 535 if (pcm_audio)536 hcp->chmap_idx = ca_id;537 else538 hcp->chmap_idx = HDMI_CODEC_CHMAP_IDX_UNKNOWN;539 540 return 0;541}542 543static int hdmi_codec_hw_params(struct snd_pcm_substream *substream,544 struct snd_pcm_hw_params *params,545 struct snd_soc_dai *dai)546{547 struct hdmi_codec_priv *hcp = snd_soc_dai_get_drvdata(dai);548 struct hdmi_codec_daifmt *cf = snd_soc_dai_dma_data_get_playback(dai);549 struct hdmi_codec_params hp = {550 .iec = {551 .status = { 0 },552 .subcode = { 0 },553 .pad = 0,554 .dig_subframe = { 0 },555 }556 };557 int ret;558 559 if (!hcp->hcd.ops->hw_params)560 return 0;561 562 dev_dbg(dai->dev, "%s() width %d rate %d channels %d\n", __func__,563 params_width(params), params_rate(params),564 params_channels(params));565 566 ret = hdmi_codec_fill_codec_params(dai,567 params_width(params),568 params_rate(params),569 params_channels(params),570 &hp);571 if (ret < 0)572 return ret;573 574 memcpy(hp.iec.status, hcp->iec_status, sizeof(hp.iec.status));575 ret = snd_pcm_fill_iec958_consumer_hw_params(params, hp.iec.status,576 sizeof(hp.iec.status));577 if (ret < 0) {578 dev_err(dai->dev, "Creating IEC958 channel status failed %d\n",579 ret);580 return ret;581 }582 583 cf->bit_fmt = params_format(params);584 return hcp->hcd.ops->hw_params(dai->dev->parent, hcp->hcd.data,585 cf, &hp);586}587 588static int hdmi_codec_prepare(struct snd_pcm_substream *substream,589 struct snd_soc_dai *dai)590{591 struct hdmi_codec_priv *hcp = snd_soc_dai_get_drvdata(dai);592 struct hdmi_codec_daifmt *cf = snd_soc_dai_dma_data_get_playback(dai);593 struct snd_pcm_runtime *runtime = substream->runtime;594 unsigned int channels = runtime->channels;595 unsigned int width = snd_pcm_format_width(runtime->format);596 unsigned int rate = runtime->rate;597 struct hdmi_codec_params hp;598 int ret;599 600 if (!hcp->hcd.ops->prepare)601 return 0;602 603 dev_dbg(dai->dev, "%s() width %d rate %d channels %d\n", __func__,604 width, rate, channels);605 606 ret = hdmi_codec_fill_codec_params(dai, width, rate, channels, &hp);607 if (ret < 0)608 return ret;609 610 memcpy(hp.iec.status, hcp->iec_status, sizeof(hp.iec.status));611 ret = snd_pcm_fill_iec958_consumer(runtime, hp.iec.status,612 sizeof(hp.iec.status));613 if (ret < 0) {614 dev_err(dai->dev, "Creating IEC958 channel status failed %d\n",615 ret);616 return ret;617 }618 619 cf->bit_fmt = runtime->format;620 return hcp->hcd.ops->prepare(dai->dev->parent, hcp->hcd.data,621 cf, &hp);622}623 624static int hdmi_codec_i2s_set_fmt(struct snd_soc_dai *dai,625 unsigned int fmt)626{627 struct hdmi_codec_daifmt *cf = snd_soc_dai_dma_data_get_playback(dai);628 629 /* Reset daifmt */630 memset(cf, 0, sizeof(*cf));631 632 switch (fmt & SND_SOC_DAIFMT_CLOCK_PROVIDER_MASK) {633 case SND_SOC_DAIFMT_CBP_CFP:634 cf->bit_clk_provider = 1;635 cf->frame_clk_provider = 1;636 break;637 case SND_SOC_DAIFMT_CBC_CFP:638 cf->frame_clk_provider = 1;639 break;640 case SND_SOC_DAIFMT_CBP_CFC:641 cf->bit_clk_provider = 1;642 break;643 case SND_SOC_DAIFMT_CBC_CFC:644 break;645 default:646 return -EINVAL;647 }648 649 switch (fmt & SND_SOC_DAIFMT_INV_MASK) {650 case SND_SOC_DAIFMT_NB_NF:651 break;652 case SND_SOC_DAIFMT_NB_IF:653 cf->frame_clk_inv = 1;654 break;655 case SND_SOC_DAIFMT_IB_NF:656 cf->bit_clk_inv = 1;657 break;658 case SND_SOC_DAIFMT_IB_IF:659 cf->frame_clk_inv = 1;660 cf->bit_clk_inv = 1;661 break;662 }663 664 switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {665 case SND_SOC_DAIFMT_I2S:666 cf->fmt = HDMI_I2S;667 break;668 case SND_SOC_DAIFMT_DSP_A:669 cf->fmt = HDMI_DSP_A;670 break;671 case SND_SOC_DAIFMT_DSP_B:672 cf->fmt = HDMI_DSP_B;673 break;674 case SND_SOC_DAIFMT_RIGHT_J:675 cf->fmt = HDMI_RIGHT_J;676 break;677 case SND_SOC_DAIFMT_LEFT_J:678 cf->fmt = HDMI_LEFT_J;679 break;680 case SND_SOC_DAIFMT_AC97:681 cf->fmt = HDMI_AC97;682 break;683 default:684 dev_err(dai->dev, "Invalid DAI interface format\n");685 return -EINVAL;686 }687 688 return 0;689}690 691static int hdmi_codec_mute(struct snd_soc_dai *dai, int mute, int direction)692{693 struct hdmi_codec_priv *hcp = snd_soc_dai_get_drvdata(dai);694 695 /*696 * ignore if direction was CAPTURE697 * and it had .no_capture_mute flag698 * see699 * snd_soc_dai_digital_mute()700 */701 if (hcp->hcd.ops->mute_stream &&702 (direction == SNDRV_PCM_STREAM_PLAYBACK ||703 !hcp->hcd.ops->no_capture_mute))704 return hcp->hcd.ops->mute_stream(dai->dev->parent,705 hcp->hcd.data,706 mute, direction);707 708 return -ENOTSUPP;709}710 711/*712 * This driver can select all SND_SOC_DAIFMT_CBx_CFx,713 * but need to be selected from Sound Card, not be auto selected.714 * Because it might be used from other driver.715 * For example,716 * ${LINUX}/drivers/gpu/drm/bridge/synopsys/dw-hdmi-i2s-audio.c717 */718static const u64 hdmi_codec_formats =719 SND_SOC_POSSIBLE_DAIFMT_NB_NF |720 SND_SOC_POSSIBLE_DAIFMT_NB_IF |721 SND_SOC_POSSIBLE_DAIFMT_IB_NF |722 SND_SOC_POSSIBLE_DAIFMT_IB_IF |723 SND_SOC_POSSIBLE_DAIFMT_I2S |724 SND_SOC_POSSIBLE_DAIFMT_DSP_A |725 SND_SOC_POSSIBLE_DAIFMT_DSP_B |726 SND_SOC_POSSIBLE_DAIFMT_RIGHT_J |727 SND_SOC_POSSIBLE_DAIFMT_LEFT_J |728 SND_SOC_POSSIBLE_DAIFMT_AC97;729 730#define HDMI_RATES (SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_44100 |\731 SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_88200 |\732 SNDRV_PCM_RATE_96000 | SNDRV_PCM_RATE_176400 |\733 SNDRV_PCM_RATE_192000)734 735#define SPDIF_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE |\736 SNDRV_PCM_FMTBIT_S24_3LE | SNDRV_PCM_FMTBIT_S24_LE)737 738/*739 * This list is only for formats allowed on the I2S bus. So there is740 * some formats listed that are not supported by HDMI interface. For741 * instance allowing the 32-bit formats enables 24-precision with CPU742 * DAIs that do not support 24-bit formats. If the extra formats cause743 * problems, we should add the video side driver an option to disable744 * them.745 */746#define I2S_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE |\747 SNDRV_PCM_FMTBIT_S24_3LE | SNDRV_PCM_FMTBIT_S24_LE |\748 SNDRV_PCM_FMTBIT_S32_LE | SNDRV_PCM_FMTBIT_IEC958_SUBFRAME_LE)749 750static struct snd_kcontrol_new hdmi_codec_controls[] = {751 {752 .access = SNDRV_CTL_ELEM_ACCESS_READ,753 .iface = SNDRV_CTL_ELEM_IFACE_PCM,754 .name = SNDRV_CTL_NAME_IEC958("", PLAYBACK, MASK),755 .info = hdmi_codec_iec958_info,756 .get = hdmi_codec_iec958_mask_get,757 },758 {759 .iface = SNDRV_CTL_ELEM_IFACE_PCM,760 .name = SNDRV_CTL_NAME_IEC958("", PLAYBACK, DEFAULT),761 .info = hdmi_codec_iec958_info,762 .get = hdmi_codec_iec958_default_get,763 .put = hdmi_codec_iec958_default_put,764 },765 {766 .access = (SNDRV_CTL_ELEM_ACCESS_READ |767 SNDRV_CTL_ELEM_ACCESS_VOLATILE),768 .iface = SNDRV_CTL_ELEM_IFACE_PCM,769 .name = "ELD",770 .info = hdmi_eld_ctl_info,771 .get = hdmi_eld_ctl_get,772 },773};774 775static int hdmi_codec_pcm_new(struct snd_soc_pcm_runtime *rtd,776 struct snd_soc_dai *dai)777{778 struct snd_soc_dai_driver *drv = dai->driver;779 struct hdmi_codec_priv *hcp = snd_soc_dai_get_drvdata(dai);780 unsigned int i;781 int ret;782 783 ret = snd_pcm_add_chmap_ctls(rtd->pcm, SNDRV_PCM_STREAM_PLAYBACK,784 NULL, drv->playback.channels_max, 0,785 &hcp->chmap_info);786 if (ret < 0)787 return ret;788 789 /* override handlers */790 hcp->chmap_info->private_data = hcp;791 hcp->chmap_info->kctl->get = hdmi_codec_chmap_ctl_get;792 793 /* default chmap supported is stereo */794 hcp->chmap_info->chmap = hdmi_codec_stereo_chmaps;795 hcp->chmap_idx = HDMI_CODEC_CHMAP_IDX_UNKNOWN;796 797 for (i = 0; i < ARRAY_SIZE(hdmi_codec_controls); i++) {798 struct snd_kcontrol *kctl;799 800 /* add ELD ctl with the device number corresponding to the PCM stream */801 kctl = snd_ctl_new1(&hdmi_codec_controls[i], dai->component);802 if (!kctl)803 return -ENOMEM;804 805 kctl->id.device = rtd->pcm->device;806 ret = snd_ctl_add(rtd->card->snd_card, kctl);807 if (ret < 0)808 return ret;809 }810 811 return 0;812}813 814static int hdmi_dai_probe(struct snd_soc_dai *dai)815{816 struct snd_soc_dapm_context *dapm;817 struct hdmi_codec_daifmt *daifmt;818 struct snd_soc_dapm_route route[] = {819 {820 .sink = "TX",821 .source = dai->driver->playback.stream_name,822 },823 {824 .sink = dai->driver->capture.stream_name,825 .source = "RX",826 },827 };828 int ret, i;829 830 dapm = snd_soc_component_get_dapm(dai->component);831 832 /* One of the directions might be omitted for unidirectional DAIs */833 for (i = 0; i < ARRAY_SIZE(route); i++) {834 if (!route[i].source || !route[i].sink)835 continue;836 837 ret = snd_soc_dapm_add_routes(dapm, &route[i], 1);838 if (ret)839 return ret;840 }841 842 daifmt = devm_kzalloc(dai->dev, sizeof(*daifmt), GFP_KERNEL);843 if (!daifmt)844 return -ENOMEM;845 846 snd_soc_dai_dma_data_set_playback(dai, daifmt);847 848 return 0;849}850 851static void hdmi_codec_jack_report(struct hdmi_codec_priv *hcp,852 unsigned int jack_status)853{854 if (jack_status != hcp->jack_status) {855 if (hcp->jack)856 snd_soc_jack_report(hcp->jack, jack_status, SND_JACK_LINEOUT);857 hcp->jack_status = jack_status;858 }859}860 861static void plugged_cb(struct device *dev, bool plugged)862{863 struct hdmi_codec_priv *hcp = dev_get_drvdata(dev);864 865 if (plugged) {866 if (hcp->hcd.ops->get_eld) {867 hcp->hcd.ops->get_eld(dev->parent, hcp->hcd.data,868 hcp->eld, sizeof(hcp->eld));869 }870 hdmi_codec_jack_report(hcp, SND_JACK_LINEOUT);871 } else {872 hdmi_codec_jack_report(hcp, 0);873 memset(hcp->eld, 0, sizeof(hcp->eld));874 }875}876 877static int hdmi_codec_set_jack(struct snd_soc_component *component,878 struct snd_soc_jack *jack,879 void *data)880{881 struct hdmi_codec_priv *hcp = snd_soc_component_get_drvdata(component);882 883 if (hcp->hcd.ops->hook_plugged_cb) {884 hcp->jack = jack;885 886 /*887 * Report the initial jack status which may have been provided888 * by the parent hdmi driver while the hpd hook was registered.889 */890 snd_soc_jack_report(jack, hcp->jack_status, SND_JACK_LINEOUT);891 892 return 0;893 }894 895 return -ENOTSUPP;896}897 898static int hdmi_dai_spdif_probe(struct snd_soc_dai *dai)899{900 struct hdmi_codec_daifmt *cf;901 int ret;902 903 ret = hdmi_dai_probe(dai);904 if (ret)905 return ret;906 907 cf = snd_soc_dai_dma_data_get_playback(dai);908 cf->fmt = HDMI_SPDIF;909 910 return 0;911}912 913static const struct snd_soc_dai_ops hdmi_codec_i2s_dai_ops = {914 .probe = hdmi_dai_probe,915 .startup = hdmi_codec_startup,916 .shutdown = hdmi_codec_shutdown,917 .hw_params = hdmi_codec_hw_params,918 .prepare = hdmi_codec_prepare,919 .set_fmt = hdmi_codec_i2s_set_fmt,920 .mute_stream = hdmi_codec_mute,921 .pcm_new = hdmi_codec_pcm_new,922 .auto_selectable_formats = &hdmi_codec_formats,923 .num_auto_selectable_formats = 1,924};925 926static const struct snd_soc_dai_ops hdmi_codec_spdif_dai_ops = {927 .probe = hdmi_dai_spdif_probe,928 .startup = hdmi_codec_startup,929 .shutdown = hdmi_codec_shutdown,930 .hw_params = hdmi_codec_hw_params,931 .mute_stream = hdmi_codec_mute,932 .pcm_new = hdmi_codec_pcm_new,933};934 935static const struct snd_soc_dai_driver hdmi_i2s_dai = {936 .name = "i2s-hifi",937 .id = DAI_ID_I2S,938 .playback = {939 .stream_name = "I2S Playback",940 .channels_min = 2,941 .channels_max = 8,942 .rates = HDMI_RATES,943 .formats = I2S_FORMATS,944 .sig_bits = 24,945 },946 .capture = {947 .stream_name = "Capture",948 .channels_min = 2,949 .channels_max = 8,950 .rates = HDMI_RATES,951 .formats = I2S_FORMATS,952 .sig_bits = 24,953 },954 .ops = &hdmi_codec_i2s_dai_ops,955};956 957static const struct snd_soc_dai_driver hdmi_spdif_dai = {958 .name = "spdif-hifi",959 .id = DAI_ID_SPDIF,960 .playback = {961 .stream_name = "SPDIF Playback",962 .channels_min = 2,963 .channels_max = 2,964 .rates = HDMI_RATES,965 .formats = SPDIF_FORMATS,966 },967 .capture = {968 .stream_name = "Capture",969 .channels_min = 2,970 .channels_max = 2,971 .rates = HDMI_RATES,972 .formats = SPDIF_FORMATS,973 },974 .ops = &hdmi_codec_spdif_dai_ops,975};976 977static int hdmi_of_xlate_dai_id(struct snd_soc_component *component,978 struct device_node *endpoint)979{980 struct hdmi_codec_priv *hcp = snd_soc_component_get_drvdata(component);981 int ret = -ENOTSUPP; /* see snd_soc_get_dai_id() */982 983 if (hcp->hcd.ops->get_dai_id)984 ret = hcp->hcd.ops->get_dai_id(component, endpoint);985 986 return ret;987}988 989static int hdmi_probe(struct snd_soc_component *component)990{991 struct hdmi_codec_priv *hcp = snd_soc_component_get_drvdata(component);992 int ret = 0;993 994 if (hcp->hcd.ops->hook_plugged_cb) {995 ret = hcp->hcd.ops->hook_plugged_cb(component->dev->parent,996 hcp->hcd.data,997 plugged_cb,998 component->dev);999 }1000 1001 return ret;1002}1003 1004static void hdmi_remove(struct snd_soc_component *component)1005{1006 struct hdmi_codec_priv *hcp = snd_soc_component_get_drvdata(component);1007 1008 if (hcp->hcd.ops->hook_plugged_cb)1009 hcp->hcd.ops->hook_plugged_cb(component->dev->parent,1010 hcp->hcd.data, NULL, NULL);1011}1012 1013static const struct snd_soc_component_driver hdmi_driver = {1014 .probe = hdmi_probe,1015 .remove = hdmi_remove,1016 .dapm_widgets = hdmi_widgets,1017 .num_dapm_widgets = ARRAY_SIZE(hdmi_widgets),1018 .of_xlate_dai_id = hdmi_of_xlate_dai_id,1019 .idle_bias_on = 1,1020 .use_pmdown_time = 1,1021 .endianness = 1,1022 .set_jack = hdmi_codec_set_jack,1023};1024 1025static int hdmi_codec_probe(struct platform_device *pdev)1026{1027 struct hdmi_codec_pdata *hcd = pdev->dev.platform_data;1028 struct snd_soc_dai_driver *daidrv;1029 struct device *dev = &pdev->dev;1030 struct hdmi_codec_priv *hcp;1031 int dai_count, i = 0;1032 int ret;1033 1034 if (!hcd) {1035 dev_err(dev, "%s: No platform data\n", __func__);1036 return -EINVAL;1037 }1038 1039 dai_count = hcd->i2s + hcd->spdif;1040 if (dai_count < 1 || !hcd->ops ||1041 (!hcd->ops->hw_params && !hcd->ops->prepare) ||1042 !hcd->ops->audio_shutdown) {1043 dev_err(dev, "%s: Invalid parameters\n", __func__);1044 return -EINVAL;1045 }1046 1047 hcp = devm_kzalloc(dev, sizeof(*hcp), GFP_KERNEL);1048 if (!hcp)1049 return -ENOMEM;1050 1051 hcp->hcd = *hcd;1052 mutex_init(&hcp->lock);1053 1054 ret = snd_pcm_create_iec958_consumer_default(hcp->iec_status,1055 sizeof(hcp->iec_status));1056 if (ret < 0)1057 return ret;1058 1059 daidrv = devm_kcalloc(dev, dai_count, sizeof(*daidrv), GFP_KERNEL);1060 if (!daidrv)1061 return -ENOMEM;1062 1063 if (hcd->i2s) {1064 daidrv[i] = hdmi_i2s_dai;1065 daidrv[i].playback.channels_max = hcd->max_i2s_channels;1066 if (hcd->no_i2s_playback)1067 memset(&daidrv[i].playback, 0,1068 sizeof(daidrv[i].playback));1069 if (hcd->no_i2s_capture)1070 memset(&daidrv[i].capture, 0,1071 sizeof(daidrv[i].capture));1072 i++;1073 }1074 1075 if (hcd->spdif) {1076 daidrv[i] = hdmi_spdif_dai;1077 if (hcd->no_spdif_playback)1078 memset(&daidrv[i].playback, 0,1079 sizeof(daidrv[i].playback));1080 if (hcd->no_spdif_capture)1081 memset(&daidrv[i].capture, 0,1082 sizeof(daidrv[i].capture));1083 }1084 1085 dev_set_drvdata(dev, hcp);1086 1087 ret = devm_snd_soc_register_component(dev, &hdmi_driver, daidrv,1088 dai_count);1089 if (ret) {1090 dev_err(dev, "%s: snd_soc_register_component() failed (%d)\n",1091 __func__, ret);1092 return ret;1093 }1094 return 0;1095}1096 1097static struct platform_driver hdmi_codec_driver = {1098 .driver = {1099 .name = HDMI_CODEC_DRV_NAME,1100 },1101 .probe = hdmi_codec_probe,1102};1103 1104module_platform_driver(hdmi_codec_driver);1105 1106MODULE_AUTHOR("Jyri Sarha <jsarha@ti.com>");1107MODULE_DESCRIPTION("HDMI Audio Codec Driver");1108MODULE_LICENSE("GPL");1109MODULE_ALIAS("platform:" HDMI_CODEC_DRV_NAME);1110