brintos

brintos / linux-shallow public Read only

0
0
Text · 30.9 KiB · 74caae5 Raw
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