diff options
Diffstat (limited to 'target/linux/brcm2708/patches-4.4/0129-bcm2835-implement-channel-map-API.patch')
-rw-r--r-- | target/linux/brcm2708/patches-4.4/0129-bcm2835-implement-channel-map-API.patch | 421 |
1 files changed, 0 insertions, 421 deletions
diff --git a/target/linux/brcm2708/patches-4.4/0129-bcm2835-implement-channel-map-API.patch b/target/linux/brcm2708/patches-4.4/0129-bcm2835-implement-channel-map-API.patch deleted file mode 100644 index 3da4fc41eb..0000000000 --- a/target/linux/brcm2708/patches-4.4/0129-bcm2835-implement-channel-map-API.patch +++ /dev/null @@ -1,421 +0,0 @@ -From dead6a5d8c3cd19b1197b60a674f898270a8e1d1 Mon Sep 17 00:00:00 2001 -From: wm4 <wm4@nowhere> -Date: Wed, 13 Jan 2016 19:43:12 +0100 -Subject: [PATCH] bcm2835: implement channel map API - -Report all layouts supported by the HDMI protocol to userspace. -Make the videocore set the correct layout according to the -userspace request. - -Some code taken from patch_hdmi.c. In particular, the HDMI channel -layout table was copied without changes - with the idea in mind that -hopefully it can be shared one day. Or at least updating it will be -simpler. - -In my tests, everything appears to work, except when outputting -FL FR RL RR. Then my receiver outputs RL on both the RL and RR -speakers, while RR is never heard. ---- - sound/arm/bcm2835-ctl.c | 276 ++++++++++++++++++++++++++++++++++++++++++++++ - sound/arm/bcm2835-pcm.c | 22 +++- - sound/arm/bcm2835-vchiq.c | 13 +++ - sound/arm/bcm2835.h | 4 + - 4 files changed, 311 insertions(+), 4 deletions(-) - ---- a/sound/arm/bcm2835-ctl.c -+++ b/sound/arm/bcm2835-ctl.c -@@ -300,6 +300,281 @@ static struct snd_kcontrol_new snd_bcm28 - }, - }; - -+struct cea_channel_speaker_allocation { -+ int ca_index; -+ int speakers[8]; -+}; -+ -+#define FL SNDRV_CHMAP_FL -+#define FR SNDRV_CHMAP_FR -+#define RL SNDRV_CHMAP_RL -+#define RR SNDRV_CHMAP_RR -+#define LFE SNDRV_CHMAP_LFE -+#define FC SNDRV_CHMAP_FC -+#define RLC SNDRV_CHMAP_RLC -+#define RRC SNDRV_CHMAP_RRC -+#define RC SNDRV_CHMAP_RC -+#define FLC SNDRV_CHMAP_FLC -+#define FRC SNDRV_CHMAP_FRC -+#define FLH SNDRV_CHMAP_TFL -+#define FRH SNDRV_CHMAP_TFR -+#define FLW SNDRV_CHMAP_FLW -+#define FRW SNDRV_CHMAP_FRW -+#define TC SNDRV_CHMAP_TC -+#define FCH SNDRV_CHMAP_TFC -+ -+/* -+ * CEA-861 channel maps -+ * -+ * Stolen from sound/pci/hda/patch_hdmi.c -+ * (unlike the source, this uses SNDRV_* constants directly, as by the -+ * map_tables array in patch_hdmi.c) -+ * Unknown entries use 0, which unfortunately is SNDRV_CHMAP_UNKNOWN instead -+ * of SNDRV_CHMAP_NA. -+ */ -+static struct cea_channel_speaker_allocation channel_allocations[] = { -+/* channel: 7 6 5 4 3 2 1 0 */ -+{ .ca_index = 0x00, .speakers = { 0, 0, 0, 0, 0, 0, FR, FL } }, -+ /* 2.1 */ -+{ .ca_index = 0x01, .speakers = { 0, 0, 0, 0, 0, LFE, FR, FL } }, -+ /* Dolby Surround */ -+{ .ca_index = 0x02, .speakers = { 0, 0, 0, 0, FC, 0, FR, FL } }, -+ /* surround40 */ -+{ .ca_index = 0x08, .speakers = { 0, 0, RR, RL, 0, 0, FR, FL } }, -+ /* surround41 */ -+{ .ca_index = 0x09, .speakers = { 0, 0, RR, RL, 0, LFE, FR, FL } }, -+ /* surround50 */ -+{ .ca_index = 0x0a, .speakers = { 0, 0, RR, RL, FC, 0, FR, FL } }, -+ /* surround51 */ -+{ .ca_index = 0x0b, .speakers = { 0, 0, RR, RL, FC, LFE, FR, FL } }, -+ /* 6.1 */ -+{ .ca_index = 0x0f, .speakers = { 0, RC, RR, RL, FC, LFE, FR, FL } }, -+ /* surround71 */ -+{ .ca_index = 0x13, .speakers = { RRC, RLC, RR, RL, FC, LFE, FR, FL } }, -+ -+{ .ca_index = 0x03, .speakers = { 0, 0, 0, 0, FC, LFE, FR, FL } }, -+{ .ca_index = 0x04, .speakers = { 0, 0, 0, RC, 0, 0, FR, FL } }, -+{ .ca_index = 0x05, .speakers = { 0, 0, 0, RC, 0, LFE, FR, FL } }, -+{ .ca_index = 0x06, .speakers = { 0, 0, 0, RC, FC, 0, FR, FL } }, -+{ .ca_index = 0x07, .speakers = { 0, 0, 0, RC, FC, LFE, FR, FL } }, -+{ .ca_index = 0x0c, .speakers = { 0, RC, RR, RL, 0, 0, FR, FL } }, -+{ .ca_index = 0x0d, .speakers = { 0, RC, RR, RL, 0, LFE, FR, FL } }, -+{ .ca_index = 0x0e, .speakers = { 0, RC, RR, RL, FC, 0, FR, FL } }, -+{ .ca_index = 0x10, .speakers = { RRC, RLC, RR, RL, 0, 0, FR, FL } }, -+{ .ca_index = 0x11, .speakers = { RRC, RLC, RR, RL, 0, LFE, FR, FL } }, -+{ .ca_index = 0x12, .speakers = { RRC, RLC, RR, RL, FC, 0, FR, FL } }, -+{ .ca_index = 0x14, .speakers = { FRC, FLC, 0, 0, 0, 0, FR, FL } }, -+{ .ca_index = 0x15, .speakers = { FRC, FLC, 0, 0, 0, LFE, FR, FL } }, -+{ .ca_index = 0x16, .speakers = { FRC, FLC, 0, 0, FC, 0, FR, FL } }, -+{ .ca_index = 0x17, .speakers = { FRC, FLC, 0, 0, FC, LFE, FR, FL } }, -+{ .ca_index = 0x18, .speakers = { FRC, FLC, 0, RC, 0, 0, FR, FL } }, -+{ .ca_index = 0x19, .speakers = { FRC, FLC, 0, RC, 0, LFE, FR, FL } }, -+{ .ca_index = 0x1a, .speakers = { FRC, FLC, 0, RC, FC, 0, FR, FL } }, -+{ .ca_index = 0x1b, .speakers = { FRC, FLC, 0, RC, FC, LFE, FR, FL } }, -+{ .ca_index = 0x1c, .speakers = { FRC, FLC, RR, RL, 0, 0, FR, FL } }, -+{ .ca_index = 0x1d, .speakers = { FRC, FLC, RR, RL, 0, LFE, FR, FL } }, -+{ .ca_index = 0x1e, .speakers = { FRC, FLC, RR, RL, FC, 0, FR, FL } }, -+{ .ca_index = 0x1f, .speakers = { FRC, FLC, RR, RL, FC, LFE, FR, FL } }, -+{ .ca_index = 0x20, .speakers = { 0, FCH, RR, RL, FC, 0, FR, FL } }, -+{ .ca_index = 0x21, .speakers = { 0, FCH, RR, RL, FC, LFE, FR, FL } }, -+{ .ca_index = 0x22, .speakers = { TC, 0, RR, RL, FC, 0, FR, FL } }, -+{ .ca_index = 0x23, .speakers = { TC, 0, RR, RL, FC, LFE, FR, FL } }, -+{ .ca_index = 0x24, .speakers = { FRH, FLH, RR, RL, 0, 0, FR, FL } }, -+{ .ca_index = 0x25, .speakers = { FRH, FLH, RR, RL, 0, LFE, FR, FL } }, -+{ .ca_index = 0x26, .speakers = { FRW, FLW, RR, RL, 0, 0, FR, FL } }, -+{ .ca_index = 0x27, .speakers = { FRW, FLW, RR, RL, 0, LFE, FR, FL } }, -+{ .ca_index = 0x28, .speakers = { TC, RC, RR, RL, FC, 0, FR, FL } }, -+{ .ca_index = 0x29, .speakers = { TC, RC, RR, RL, FC, LFE, FR, FL } }, -+{ .ca_index = 0x2a, .speakers = { FCH, RC, RR, RL, FC, 0, FR, FL } }, -+{ .ca_index = 0x2b, .speakers = { FCH, RC, RR, RL, FC, LFE, FR, FL } }, -+{ .ca_index = 0x2c, .speakers = { TC, FCH, RR, RL, FC, 0, FR, FL } }, -+{ .ca_index = 0x2d, .speakers = { TC, FCH, RR, RL, FC, LFE, FR, FL } }, -+{ .ca_index = 0x2e, .speakers = { FRH, FLH, RR, RL, FC, 0, FR, FL } }, -+{ .ca_index = 0x2f, .speakers = { FRH, FLH, RR, RL, FC, LFE, FR, FL } }, -+{ .ca_index = 0x30, .speakers = { FRW, FLW, RR, RL, FC, 0, FR, FL } }, -+{ .ca_index = 0x31, .speakers = { FRW, FLW, RR, RL, FC, LFE, FR, FL } }, -+}; -+ -+static int snd_bcm2835_chmap_ctl_tlv(struct snd_kcontrol *kcontrol, int op_flag, -+ unsigned int size, unsigned int __user *tlv) -+{ -+ unsigned int __user *dst; -+ int count = 0; -+ int i; -+ -+ if (size < 8) -+ return -ENOMEM; -+ if (put_user(SNDRV_CTL_TLVT_CONTAINER, tlv)) -+ return -EFAULT; -+ size -= 8; -+ dst = tlv + 2; -+ for (i = 0; i < ARRAY_SIZE(channel_allocations); i++) { -+ struct cea_channel_speaker_allocation *ch = &channel_allocations[i]; -+ int num_chs = 0; -+ int chs_bytes; -+ int c; -+ -+ for (c = 0; c < 8; c++) { -+ if (ch->speakers[c]) -+ num_chs++; -+ } -+ -+ chs_bytes = num_chs * 4; -+ if (size < 8) -+ return -ENOMEM; -+ if (put_user(SNDRV_CTL_TLVT_CHMAP_FIXED, dst) || -+ put_user(chs_bytes, dst + 1)) -+ return -EFAULT; -+ dst += 2; -+ size -= 8; -+ count += 8; -+ if (size < chs_bytes) -+ return -ENOMEM; -+ size -= chs_bytes; -+ count += chs_bytes; -+ for (c = 0; c < 8; c++) { -+ int sp = ch->speakers[7 - c]; -+ if (sp) { -+ if (put_user(sp, dst)) -+ return -EFAULT; -+ dst++; -+ } -+ } -+ } -+ if (put_user(count, tlv + 1)) -+ return -EFAULT; -+ return 0; -+} -+ -+static int snd_bcm2835_chmap_ctl_get(struct snd_kcontrol *kcontrol, -+ struct snd_ctl_elem_value *ucontrol) -+{ -+ struct snd_pcm_chmap *info = snd_kcontrol_chip(kcontrol); -+ bcm2835_chip_t *chip = info->private_data; -+ unsigned int idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id); -+ struct snd_pcm_substream *substream = snd_pcm_chmap_substream(info, idx); -+ struct cea_channel_speaker_allocation *ch = NULL; -+ int cur = 0; -+ int i; -+ -+ if (!substream || !substream->runtime) -+ return -ENODEV; -+ -+ for (i = 0; i < ARRAY_SIZE(channel_allocations); i++) { -+ if (channel_allocations[i].ca_index == chip->cea_chmap) -+ ch = &channel_allocations[i]; -+ } -+ -+ /* If no layout was set yet, return a dummy. Apparently the userspace -+ * API will be confused if we don't. */ -+ if (!ch) -+ ch = &channel_allocations[0]; -+ -+ for (i = 0; i < 8; i++) { -+ if (ch->speakers[7 - i]) -+ ucontrol->value.integer.value[cur++] = ch->speakers[7 - i]; -+ } -+ while (cur < 8) -+ ucontrol->value.integer.value[cur++] = SNDRV_CHMAP_NA; -+ return 0; -+} -+ -+static int snd_bcm2835_chmap_ctl_put(struct snd_kcontrol *kcontrol, -+ struct snd_ctl_elem_value *ucontrol) -+{ -+ struct snd_pcm_chmap *info = snd_kcontrol_chip(kcontrol); -+ bcm2835_chip_t *chip = info->private_data; -+ unsigned int idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id); -+ struct snd_pcm_substream *substream = snd_pcm_chmap_substream(info, idx); -+ int i, prepared = 0, cea_chmap = -1; -+ int remap[8]; -+ -+ if (!substream || !substream->runtime) -+ return -ENODEV; -+ -+ switch (substream->runtime->status->state) { -+ case SNDRV_PCM_STATE_OPEN: -+ case SNDRV_PCM_STATE_SETUP: -+ break; -+ case SNDRV_PCM_STATE_PREPARED: -+ prepared = 1; -+ break; -+ default: -+ return -EBUSY; -+ } -+ -+ for (i = 0; i < ARRAY_SIZE(channel_allocations); i++) { -+ struct cea_channel_speaker_allocation *ch = &channel_allocations[i]; -+ int matches = 1; -+ int cur = 0; -+ int x; -+ memset(remap, 0, sizeof(remap)); -+ for (x = 0; x < substream->runtime->channels; x++) { -+ int sp = ucontrol->value.integer.value[x]; -+ while (cur < 8 && !ch->speakers[7 - cur]) -+ cur++; -+ if (cur >= 8) { -+ /* user has more channels than ch */ -+ matches = 0; -+ break; -+ } -+ if (ch->speakers[7 - cur] != sp) { -+ matches = 0; -+ break; -+ } -+ remap[x] = cur; -+ cur++; -+ } -+ for (x = cur; x < 8; x++) { -+ if (ch->speakers[7 - x]) { -+ /* ch has more channels than user */ -+ matches = 0; -+ break; -+ } -+ } -+ if (matches) { -+ cea_chmap = ch->ca_index; -+ break; -+ } -+ } -+ -+ if (cea_chmap < 0) -+ return -EINVAL; -+ -+ /* don't change the layout if another substream is active */ -+ if (chip->opened != (1 << substream->number) && chip->cea_chmap != cea_chmap) -+ return -EBUSY; /* unsure whether this is a good error code */ -+ -+ chip->cea_chmap = cea_chmap; -+ for (i = 0; i < 8; i++) -+ chip->map_channels[i] = remap[i]; -+ if (prepared) -+ snd_bcm2835_pcm_prepare_again(substream); -+ return 0; -+} -+ -+static int snd_bcm2835_add_chmap_ctl(bcm2835_chip_t * chip) -+{ -+ struct snd_pcm_chmap *chmap; -+ struct snd_kcontrol *kctl; -+ int err, i; -+ -+ err = snd_pcm_add_chmap_ctls(chip->pcm, -+ SNDRV_PCM_STREAM_PLAYBACK, -+ NULL, 8, 0, &chmap); -+ if (err < 0) -+ return err; -+ /* override handlers */ -+ chmap->private_data = chip; -+ kctl = chmap->kctl; -+ for (i = 0; i < kctl->count; i++) -+ kctl->vd[i].access |= SNDRV_CTL_ELEM_ACCESS_WRITE; -+ kctl->get = snd_bcm2835_chmap_ctl_get; -+ kctl->put = snd_bcm2835_chmap_ctl_put; -+ kctl->tlv.c = snd_bcm2835_chmap_ctl_tlv; -+ return 0; -+} -+ - int snd_bcm2835_new_ctl(bcm2835_chip_t * chip) - { - int err; -@@ -313,6 +588,7 @@ int snd_bcm2835_new_ctl(bcm2835_chip_t * - if (err < 0) - return err; - } -+ snd_bcm2835_add_chmap_ctl(chip); - for (idx = 0; idx < ARRAY_SIZE(snd_bcm2835_spdif); idx++) { - err = snd_ctl_add(chip->card, - snd_ctl_new1(&snd_bcm2835_spdif[idx], chip)); ---- a/sound/arm/bcm2835-pcm.c -+++ b/sound/arm/bcm2835-pcm.c -@@ -231,6 +231,9 @@ static int snd_bcm2835_playback_open_gen - - chip->alsa_stream[idx] = alsa_stream; - -+ if (!chip->opened) -+ chip->cea_chmap = -1; -+ - chip->opened |= (1 << idx); - alsa_stream->open = 1; - alsa_stream->draining = 1; -@@ -341,8 +344,7 @@ static int snd_bcm2835_pcm_hw_free(struc - return snd_pcm_lib_free_pages(substream); - } - --/* prepare callback */ --static int snd_bcm2835_pcm_prepare(struct snd_pcm_substream *substream) -+int snd_bcm2835_pcm_prepare_again(struct snd_pcm_substream *substream) - { - bcm2835_chip_t *chip = snd_pcm_substream_chip(substream); - struct snd_pcm_runtime *runtime = substream->runtime; -@@ -350,8 +352,6 @@ static int snd_bcm2835_pcm_prepare(struc - int channels; - int err; - -- audio_info(" .. IN\n"); -- - /* notify the vchiq that it should enter spdif passthrough mode by - * setting channels=0 (see - * https://github.com/raspberrypi/linux/issues/528) */ -@@ -367,6 +367,20 @@ static int snd_bcm2835_pcm_prepare(struc - audio_error(" error setting hw params\n"); - } - -+ return err; -+} -+ -+/* prepare callback */ -+static int snd_bcm2835_pcm_prepare(struct snd_pcm_substream *substream) -+{ -+ bcm2835_chip_t *chip = snd_pcm_substream_chip(substream); -+ struct snd_pcm_runtime *runtime = substream->runtime; -+ bcm2835_alsa_stream_t *alsa_stream = runtime->private_data; -+ -+ audio_info(" .. IN\n"); -+ -+ snd_bcm2835_pcm_prepare_again(substream); -+ - bcm2835_audio_setup(alsa_stream); - - /* in preparation of the stream, set the controls (volume level) of the stream */ ---- a/sound/arm/bcm2835-vchiq.c -+++ b/sound/arm/bcm2835-vchiq.c -@@ -570,6 +570,8 @@ int bcm2835_audio_set_params(bcm2835_als - VC_AUDIO_MSG_T m; - AUDIO_INSTANCE_T *instance = alsa_stream->instance; - int32_t success; -+ uint32_t chmap_value; -+ int i; - int ret; - LOG_DBG(" .. IN\n"); - -@@ -593,10 +595,21 @@ int bcm2835_audio_set_params(bcm2835_als - - instance->result = -1; - -+ if (alsa_stream->chip->cea_chmap >= 0) { -+ chmap_value = (unsigned)alsa_stream->chip->cea_chmap << 24; -+ } else { -+ chmap_value = 0; /* force stereo */ -+ for (i = 0; i < 8; i++) -+ alsa_stream->chip->map_channels[i] = i; -+ } -+ for (i = 0; i < 8; i++) -+ chmap_value |= alsa_stream->chip->map_channels[i] << (i * 3); -+ - m.type = VC_AUDIO_MSG_TYPE_CONFIG; - m.u.config.channels = channels; - m.u.config.samplerate = samplerate; - m.u.config.bps = bps; -+ m.u.config.channelmap = chmap_value; - - /* Create the message available completion */ - init_completion(&instance->msg_avail_comp); ---- a/sound/arm/bcm2835.h -+++ b/sound/arm/bcm2835.h -@@ -107,6 +107,8 @@ typedef struct bcm2835_chip { - int old_volume; /* stores the volume value whist muted */ - int dest; - int mute; -+ int cea_chmap; /* currently requested Audio InfoFrame Data Byte 4 */ -+ int map_channels[8]; - - unsigned int opened; - unsigned int spdif_status; -@@ -149,6 +151,8 @@ int snd_bcm2835_new_ctl(bcm2835_chip_t * - int snd_bcm2835_new_pcm(bcm2835_chip_t * chip); - int snd_bcm2835_new_spdif_pcm(bcm2835_chip_t * chip); - -+int snd_bcm2835_pcm_prepare_again(struct snd_pcm_substream *substream); -+ - int bcm2835_audio_open(bcm2835_alsa_stream_t * alsa_stream); - int bcm2835_audio_close(bcm2835_alsa_stream_t * alsa_stream); - int bcm2835_audio_set_params(bcm2835_alsa_stream_t * alsa_stream, |