^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0-or-later
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * Driver for Digigram pcxhr compatible soundcards
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) * main file with alsa callbacks
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) * Copyright (c) 2004 by Digigram <alsa@digigram.com>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) #include <linux/init.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) #include <linux/interrupt.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) #include <linux/slab.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) #include <linux/pci.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) #include <linux/dma-mapping.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) #include <linux/delay.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) #include <linux/module.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) #include <linux/mutex.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) #include <sound/core.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) #include <sound/initval.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) #include <sound/info.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) #include <sound/control.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) #include <sound/pcm.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) #include <sound/pcm_params.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) #include "pcxhr.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) #include "pcxhr_mixer.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) #include "pcxhr_hwdep.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) #include "pcxhr_core.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) #include "pcxhr_mix22.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) #define DRIVER_NAME "pcxhr"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) MODULE_AUTHOR("Markus Bollinger <bollinger@digigram.com>, "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) "Marc Titinger <titinger@digigram.com>");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) MODULE_DESCRIPTION("Digigram " DRIVER_NAME " " PCXHR_DRIVER_VERSION_STRING);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) MODULE_LICENSE("GPL");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) MODULE_SUPPORTED_DEVICE("{{Digigram," DRIVER_NAME "}}");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; /* Index 0-MAX */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; /* ID for this card */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) static bool enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP;/* Enable this card */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) static bool mono[SNDRV_CARDS]; /* capture mono only */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) module_param_array(index, int, NULL, 0444);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) MODULE_PARM_DESC(index, "Index value for Digigram " DRIVER_NAME " soundcard");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) module_param_array(id, charp, NULL, 0444);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) MODULE_PARM_DESC(id, "ID string for Digigram " DRIVER_NAME " soundcard");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) module_param_array(enable, bool, NULL, 0444);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) MODULE_PARM_DESC(enable, "Enable Digigram " DRIVER_NAME " soundcard");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) module_param_array(mono, bool, NULL, 0444);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) MODULE_PARM_DESC(mono, "Mono capture mode (default is stereo)");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) enum {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) PCI_ID_VX882HR,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) PCI_ID_PCX882HR,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) PCI_ID_VX881HR,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) PCI_ID_PCX881HR,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) PCI_ID_VX882E,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) PCI_ID_PCX882E,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) PCI_ID_VX881E,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) PCI_ID_PCX881E,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) PCI_ID_VX1222HR,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) PCI_ID_PCX1222HR,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) PCI_ID_VX1221HR,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) PCI_ID_PCX1221HR,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) PCI_ID_VX1222E,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) PCI_ID_PCX1222E,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) PCI_ID_VX1221E,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) PCI_ID_PCX1221E,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) PCI_ID_VX222HR,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) PCI_ID_VX222E,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) PCI_ID_PCX22HR,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) PCI_ID_PCX22E,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) PCI_ID_VX222HRMIC,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) PCI_ID_VX222E_MIC,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) PCI_ID_PCX924HR,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) PCI_ID_PCX924E,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) PCI_ID_PCX924HRMIC,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) PCI_ID_PCX924E_MIC,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) PCI_ID_VX442HR,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) PCI_ID_PCX442HR,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) PCI_ID_VX442E,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) PCI_ID_PCX442E,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) PCI_ID_VX822HR,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) PCI_ID_PCX822HR,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) PCI_ID_VX822E,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) PCI_ID_PCX822E,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) PCI_ID_LAST
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) static const struct pci_device_id pcxhr_ids[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) { 0x10b5, 0x9656, 0x1369, 0xb001, 0, 0, PCI_ID_VX882HR, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) { 0x10b5, 0x9656, 0x1369, 0xb101, 0, 0, PCI_ID_PCX882HR, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) { 0x10b5, 0x9656, 0x1369, 0xb201, 0, 0, PCI_ID_VX881HR, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) { 0x10b5, 0x9656, 0x1369, 0xb301, 0, 0, PCI_ID_PCX881HR, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) { 0x10b5, 0x9056, 0x1369, 0xb021, 0, 0, PCI_ID_VX882E, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) { 0x10b5, 0x9056, 0x1369, 0xb121, 0, 0, PCI_ID_PCX882E, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) { 0x10b5, 0x9056, 0x1369, 0xb221, 0, 0, PCI_ID_VX881E, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) { 0x10b5, 0x9056, 0x1369, 0xb321, 0, 0, PCI_ID_PCX881E, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) { 0x10b5, 0x9656, 0x1369, 0xb401, 0, 0, PCI_ID_VX1222HR, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) { 0x10b5, 0x9656, 0x1369, 0xb501, 0, 0, PCI_ID_PCX1222HR, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) { 0x10b5, 0x9656, 0x1369, 0xb601, 0, 0, PCI_ID_VX1221HR, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) { 0x10b5, 0x9656, 0x1369, 0xb701, 0, 0, PCI_ID_PCX1221HR, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) { 0x10b5, 0x9056, 0x1369, 0xb421, 0, 0, PCI_ID_VX1222E, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) { 0x10b5, 0x9056, 0x1369, 0xb521, 0, 0, PCI_ID_PCX1222E, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) { 0x10b5, 0x9056, 0x1369, 0xb621, 0, 0, PCI_ID_VX1221E, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) { 0x10b5, 0x9056, 0x1369, 0xb721, 0, 0, PCI_ID_PCX1221E, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) { 0x10b5, 0x9056, 0x1369, 0xba01, 0, 0, PCI_ID_VX222HR, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) { 0x10b5, 0x9056, 0x1369, 0xba21, 0, 0, PCI_ID_VX222E, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) { 0x10b5, 0x9056, 0x1369, 0xbd01, 0, 0, PCI_ID_PCX22HR, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) { 0x10b5, 0x9056, 0x1369, 0xbd21, 0, 0, PCI_ID_PCX22E, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) { 0x10b5, 0x9056, 0x1369, 0xbc01, 0, 0, PCI_ID_VX222HRMIC, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) { 0x10b5, 0x9056, 0x1369, 0xbc21, 0, 0, PCI_ID_VX222E_MIC, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) { 0x10b5, 0x9056, 0x1369, 0xbb01, 0, 0, PCI_ID_PCX924HR, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) { 0x10b5, 0x9056, 0x1369, 0xbb21, 0, 0, PCI_ID_PCX924E, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) { 0x10b5, 0x9056, 0x1369, 0xbf01, 0, 0, PCI_ID_PCX924HRMIC, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) { 0x10b5, 0x9056, 0x1369, 0xbf21, 0, 0, PCI_ID_PCX924E_MIC, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) { 0x10b5, 0x9656, 0x1369, 0xd001, 0, 0, PCI_ID_VX442HR, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) { 0x10b5, 0x9656, 0x1369, 0xd101, 0, 0, PCI_ID_PCX442HR, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) { 0x10b5, 0x9056, 0x1369, 0xd021, 0, 0, PCI_ID_VX442E, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) { 0x10b5, 0x9056, 0x1369, 0xd121, 0, 0, PCI_ID_PCX442E, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) { 0x10b5, 0x9656, 0x1369, 0xd201, 0, 0, PCI_ID_VX822HR, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) { 0x10b5, 0x9656, 0x1369, 0xd301, 0, 0, PCI_ID_PCX822HR, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) { 0x10b5, 0x9056, 0x1369, 0xd221, 0, 0, PCI_ID_VX822E, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) { 0x10b5, 0x9056, 0x1369, 0xd321, 0, 0, PCI_ID_PCX822E, },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) { 0, }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) MODULE_DEVICE_TABLE(pci, pcxhr_ids);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) struct board_parameters {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) char* board_name;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) short playback_chips;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) short capture_chips;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) short fw_file_set;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) short firmware_num;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) static const struct board_parameters pcxhr_board_params[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) [PCI_ID_VX882HR] = { "VX882HR", 4, 4, 0, 41 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) [PCI_ID_PCX882HR] = { "PCX882HR", 4, 4, 0, 41 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) [PCI_ID_VX881HR] = { "VX881HR", 4, 4, 0, 41 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) [PCI_ID_PCX881HR] = { "PCX881HR", 4, 4, 0, 41 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) [PCI_ID_VX882E] = { "VX882e", 4, 4, 1, 41 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) [PCI_ID_PCX882E] = { "PCX882e", 4, 4, 1, 41 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) [PCI_ID_VX881E] = { "VX881e", 4, 4, 1, 41 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) [PCI_ID_PCX881E] = { "PCX881e", 4, 4, 1, 41 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) [PCI_ID_VX1222HR] = { "VX1222HR", 6, 1, 2, 42 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) [PCI_ID_PCX1222HR] = { "PCX1222HR", 6, 1, 2, 42 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) [PCI_ID_VX1221HR] = { "VX1221HR", 6, 1, 2, 42 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) [PCI_ID_PCX1221HR] = { "PCX1221HR", 6, 1, 2, 42 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) [PCI_ID_VX1222E] = { "VX1222e", 6, 1, 3, 42 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) [PCI_ID_PCX1222E] = { "PCX1222e", 6, 1, 3, 42 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) [PCI_ID_VX1221E] = { "VX1221e", 6, 1, 3, 42 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) [PCI_ID_PCX1221E] = { "PCX1221e", 6, 1, 3, 42 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) [PCI_ID_VX222HR] = { "VX222HR", 1, 1, 4, 44 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) [PCI_ID_VX222E] = { "VX222e", 1, 1, 4, 44 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) [PCI_ID_PCX22HR] = { "PCX22HR", 1, 0, 4, 44 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) [PCI_ID_PCX22E] = { "PCX22e", 1, 0, 4, 44 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) [PCI_ID_VX222HRMIC] = { "VX222HR-Mic", 1, 1, 5, 44 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) [PCI_ID_VX222E_MIC] = { "VX222e-Mic", 1, 1, 5, 44 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) [PCI_ID_PCX924HR] = { "PCX924HR", 1, 1, 5, 44 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) [PCI_ID_PCX924E] = { "PCX924e", 1, 1, 5, 44 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) [PCI_ID_PCX924HRMIC] = { "PCX924HR-Mic", 1, 1, 5, 44 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) [PCI_ID_PCX924E_MIC] = { "PCX924e-Mic", 1, 1, 5, 44 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) [PCI_ID_VX442HR] = { "VX442HR", 2, 2, 0, 41 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) [PCI_ID_PCX442HR] = { "PCX442HR", 2, 2, 0, 41 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) [PCI_ID_VX442E] = { "VX442e", 2, 2, 1, 41 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) [PCI_ID_PCX442E] = { "PCX442e", 2, 2, 1, 41 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) [PCI_ID_VX822HR] = { "VX822HR", 4, 1, 2, 42 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) [PCI_ID_PCX822HR] = { "PCX822HR", 4, 1, 2, 42 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) [PCI_ID_VX822E] = { "VX822e", 4, 1, 3, 42 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) [PCI_ID_PCX822E] = { "PCX822e", 4, 1, 3, 42 },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) /* boards without hw AES1 and SRC onboard are all using fw_file_set==4 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) /* VX222HR, VX222e, PCX22HR and PCX22e */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) #define PCXHR_BOARD_HAS_AES1(x) (x->fw_file_set != 4)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) /* some boards do not support 192kHz on digital AES input plugs */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) #define PCXHR_BOARD_AESIN_NO_192K(x) ((x->capture_chips == 0) || \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) (x->fw_file_set == 0) || \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) (x->fw_file_set == 2))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) static int pcxhr_pll_freq_register(unsigned int freq, unsigned int* pllreg,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) unsigned int* realfreq)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) unsigned int reg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) if (freq < 6900 || freq > 110000)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) reg = (28224000 * 2) / freq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) reg = (reg - 1) / 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) if (reg < 0x200)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) *pllreg = reg + 0x800;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) else if (reg < 0x400)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) *pllreg = reg & 0x1ff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) else if (reg < 0x800) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) *pllreg = ((reg >> 1) & 0x1ff) + 0x200;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) reg &= ~1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) *pllreg = ((reg >> 2) & 0x1ff) + 0x400;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) reg &= ~3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) if (realfreq)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) *realfreq = (28224000 / (reg + 1));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) #define PCXHR_FREQ_REG_MASK 0x1f
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) #define PCXHR_FREQ_QUARTZ_48000 0x00
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) #define PCXHR_FREQ_QUARTZ_24000 0x01
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) #define PCXHR_FREQ_QUARTZ_12000 0x09
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) #define PCXHR_FREQ_QUARTZ_32000 0x08
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) #define PCXHR_FREQ_QUARTZ_16000 0x04
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) #define PCXHR_FREQ_QUARTZ_8000 0x0c
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) #define PCXHR_FREQ_QUARTZ_44100 0x02
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) #define PCXHR_FREQ_QUARTZ_22050 0x0a
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) #define PCXHR_FREQ_QUARTZ_11025 0x06
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) #define PCXHR_FREQ_PLL 0x05
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) #define PCXHR_FREQ_QUARTZ_192000 0x10
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) #define PCXHR_FREQ_QUARTZ_96000 0x18
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) #define PCXHR_FREQ_QUARTZ_176400 0x14
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) #define PCXHR_FREQ_QUARTZ_88200 0x1c
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) #define PCXHR_FREQ_QUARTZ_128000 0x12
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) #define PCXHR_FREQ_QUARTZ_64000 0x1a
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) #define PCXHR_FREQ_WORD_CLOCK 0x0f
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) #define PCXHR_FREQ_SYNC_AES 0x0e
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) #define PCXHR_FREQ_AES_1 0x07
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) #define PCXHR_FREQ_AES_2 0x0b
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) #define PCXHR_FREQ_AES_3 0x03
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) #define PCXHR_FREQ_AES_4 0x0d
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) static int pcxhr_get_clock_reg(struct pcxhr_mgr *mgr, unsigned int rate,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) unsigned int *reg, unsigned int *freq)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) unsigned int val, realfreq, pllreg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) struct pcxhr_rmh rmh;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) realfreq = rate;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) switch (mgr->use_clock_type) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) case PCXHR_CLOCK_TYPE_INTERNAL : /* clock by quartz or pll */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) switch (rate) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) case 48000 : val = PCXHR_FREQ_QUARTZ_48000; break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) case 24000 : val = PCXHR_FREQ_QUARTZ_24000; break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) case 12000 : val = PCXHR_FREQ_QUARTZ_12000; break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) case 32000 : val = PCXHR_FREQ_QUARTZ_32000; break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) case 16000 : val = PCXHR_FREQ_QUARTZ_16000; break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) case 8000 : val = PCXHR_FREQ_QUARTZ_8000; break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) case 44100 : val = PCXHR_FREQ_QUARTZ_44100; break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) case 22050 : val = PCXHR_FREQ_QUARTZ_22050; break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) case 11025 : val = PCXHR_FREQ_QUARTZ_11025; break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) case 192000 : val = PCXHR_FREQ_QUARTZ_192000; break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) case 96000 : val = PCXHR_FREQ_QUARTZ_96000; break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) case 176400 : val = PCXHR_FREQ_QUARTZ_176400; break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) case 88200 : val = PCXHR_FREQ_QUARTZ_88200; break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) case 128000 : val = PCXHR_FREQ_QUARTZ_128000; break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) case 64000 : val = PCXHR_FREQ_QUARTZ_64000; break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) default :
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) val = PCXHR_FREQ_PLL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) /* get the value for the pll register */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) err = pcxhr_pll_freq_register(rate, &pllreg, &realfreq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) pcxhr_init_rmh(&rmh, CMD_ACCESS_IO_WRITE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) rmh.cmd[0] |= IO_NUM_REG_GENCLK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) rmh.cmd[1] = pllreg & MASK_DSP_WORD;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) rmh.cmd[2] = pllreg >> 24;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) rmh.cmd_len = 3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) err = pcxhr_send_msg(mgr, &rmh);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) if (err < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) dev_err(&mgr->pci->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) "error CMD_ACCESS_IO_WRITE "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) "for PLL register : %x!\n", err);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) case PCXHR_CLOCK_TYPE_WORD_CLOCK:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) val = PCXHR_FREQ_WORD_CLOCK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) case PCXHR_CLOCK_TYPE_AES_SYNC:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) val = PCXHR_FREQ_SYNC_AES;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) case PCXHR_CLOCK_TYPE_AES_1:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) val = PCXHR_FREQ_AES_1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) case PCXHR_CLOCK_TYPE_AES_2:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) val = PCXHR_FREQ_AES_2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) case PCXHR_CLOCK_TYPE_AES_3:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) val = PCXHR_FREQ_AES_3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) case PCXHR_CLOCK_TYPE_AES_4:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) val = PCXHR_FREQ_AES_4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) *reg = val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) *freq = realfreq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) static int pcxhr_sub_set_clock(struct pcxhr_mgr *mgr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) unsigned int rate,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) int *changed)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) unsigned int val, realfreq, speed;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) struct pcxhr_rmh rmh;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) err = pcxhr_get_clock_reg(mgr, rate, &val, &realfreq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) /* codec speed modes */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) if (rate < 55000)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) speed = 0; /* single speed */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) else if (rate < 100000)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) speed = 1; /* dual speed */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) speed = 2; /* quad speed */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) if (mgr->codec_speed != speed) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) pcxhr_init_rmh(&rmh, CMD_ACCESS_IO_WRITE); /* mute outputs */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) rmh.cmd[0] |= IO_NUM_REG_MUTE_OUT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) if (DSP_EXT_CMD_SET(mgr)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) rmh.cmd[1] = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) rmh.cmd_len = 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) err = pcxhr_send_msg(mgr, &rmh);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) pcxhr_init_rmh(&rmh, CMD_ACCESS_IO_WRITE); /* set speed ratio */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339) rmh.cmd[0] |= IO_NUM_SPEED_RATIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) rmh.cmd[1] = speed;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) rmh.cmd_len = 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) err = pcxhr_send_msg(mgr, &rmh);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) /* set the new frequency */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347) dev_dbg(&mgr->pci->dev, "clock register : set %x\n", val);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348) err = pcxhr_write_io_num_reg_cont(mgr, PCXHR_FREQ_REG_MASK,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349) val, changed);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353) mgr->sample_rate_real = realfreq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354) mgr->cur_clock_type = mgr->use_clock_type;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356) /* unmute after codec speed modes */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357) if (mgr->codec_speed != speed) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358) pcxhr_init_rmh(&rmh, CMD_ACCESS_IO_READ); /* unmute outputs */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359) rmh.cmd[0] |= IO_NUM_REG_MUTE_OUT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360) if (DSP_EXT_CMD_SET(mgr)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361) rmh.cmd[1] = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362) rmh.cmd_len = 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364) err = pcxhr_send_msg(mgr, &rmh);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367) mgr->codec_speed = speed; /* save new codec speed */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370) dev_dbg(&mgr->pci->dev, "pcxhr_sub_set_clock to %dHz (realfreq=%d)\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371) rate, realfreq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375) #define PCXHR_MODIFY_CLOCK_S_BIT 0x04
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377) #define PCXHR_IRQ_TIMER_FREQ 92000
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378) #define PCXHR_IRQ_TIMER_PERIOD 48
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380) int pcxhr_set_clock(struct pcxhr_mgr *mgr, unsigned int rate)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382) struct pcxhr_rmh rmh;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383) int err, changed;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385) if (rate == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386) return 0; /* nothing to do */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388) if (mgr->is_hr_stereo)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389) err = hr222_sub_set_clock(mgr, rate, &changed);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391) err = pcxhr_sub_set_clock(mgr, rate, &changed);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396) if (changed) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397) pcxhr_init_rmh(&rmh, CMD_MODIFY_CLOCK);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398) rmh.cmd[0] |= PCXHR_MODIFY_CLOCK_S_BIT; /* resync fifos */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399) if (rate < PCXHR_IRQ_TIMER_FREQ)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400) rmh.cmd[1] = PCXHR_IRQ_TIMER_PERIOD;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402) rmh.cmd[1] = PCXHR_IRQ_TIMER_PERIOD * 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403) rmh.cmd[2] = rate;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404) rmh.cmd_len = 3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405) err = pcxhr_send_msg(mgr, &rmh);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 407) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 408) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 409) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 410) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 411)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 412)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 413) static int pcxhr_sub_get_external_clock(struct pcxhr_mgr *mgr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 414) enum pcxhr_clock_type clock_type,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 415) int *sample_rate)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 416) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 417) struct pcxhr_rmh rmh;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 418) unsigned char reg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 419) int err, rate;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 420)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 421) switch (clock_type) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 422) case PCXHR_CLOCK_TYPE_WORD_CLOCK:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 423) reg = REG_STATUS_WORD_CLOCK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 424) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 425) case PCXHR_CLOCK_TYPE_AES_SYNC:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 426) reg = REG_STATUS_AES_SYNC;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 427) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 428) case PCXHR_CLOCK_TYPE_AES_1:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 429) reg = REG_STATUS_AES_1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 430) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 431) case PCXHR_CLOCK_TYPE_AES_2:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 432) reg = REG_STATUS_AES_2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 433) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 434) case PCXHR_CLOCK_TYPE_AES_3:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 435) reg = REG_STATUS_AES_3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 436) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 437) case PCXHR_CLOCK_TYPE_AES_4:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 438) reg = REG_STATUS_AES_4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 439) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 440) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 441) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 442) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 443) pcxhr_init_rmh(&rmh, CMD_ACCESS_IO_READ);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 444) rmh.cmd_len = 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 445) rmh.cmd[0] |= IO_NUM_REG_STATUS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 446) if (mgr->last_reg_stat != reg) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 447) rmh.cmd[1] = reg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 448) err = pcxhr_send_msg(mgr, &rmh);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 449) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 450) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 451) udelay(100); /* wait minimum 2 sample_frames at 32kHz ! */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 452) mgr->last_reg_stat = reg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 453) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 454) rmh.cmd[1] = REG_STATUS_CURRENT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 455) err = pcxhr_send_msg(mgr, &rmh);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 456) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 457) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 458) switch (rmh.stat[1] & 0x0f) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 459) case REG_STATUS_SYNC_32000 : rate = 32000; break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 460) case REG_STATUS_SYNC_44100 : rate = 44100; break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 461) case REG_STATUS_SYNC_48000 : rate = 48000; break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 462) case REG_STATUS_SYNC_64000 : rate = 64000; break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 463) case REG_STATUS_SYNC_88200 : rate = 88200; break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 464) case REG_STATUS_SYNC_96000 : rate = 96000; break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 465) case REG_STATUS_SYNC_128000 : rate = 128000; break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 466) case REG_STATUS_SYNC_176400 : rate = 176400; break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 467) case REG_STATUS_SYNC_192000 : rate = 192000; break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 468) default: rate = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 469) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 470) dev_dbg(&mgr->pci->dev, "External clock is at %d Hz\n", rate);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 471) *sample_rate = rate;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 472) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 473) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 474)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 475)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 476) int pcxhr_get_external_clock(struct pcxhr_mgr *mgr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 477) enum pcxhr_clock_type clock_type,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 478) int *sample_rate)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 479) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 480) if (mgr->is_hr_stereo)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 481) return hr222_get_external_clock(mgr, clock_type,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 482) sample_rate);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 483) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 484) return pcxhr_sub_get_external_clock(mgr, clock_type,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 485) sample_rate);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 486) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 487)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 488) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 489) * start or stop playback/capture substream
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 490) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 491) static int pcxhr_set_stream_state(struct snd_pcxhr *chip,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 492) struct pcxhr_stream *stream)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 493) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 494) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 495) struct pcxhr_rmh rmh;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 496) int stream_mask, start;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 497)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 498) if (stream->status == PCXHR_STREAM_STATUS_SCHEDULE_RUN)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 499) start = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 500) else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 501) if (stream->status != PCXHR_STREAM_STATUS_SCHEDULE_STOP) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 502) dev_err(chip->card->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 503) "pcxhr_set_stream_state CANNOT be stopped\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 504) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 505) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 506) start = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 507) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 508) if (!stream->substream)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 509) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 510)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 511) stream->timer_abs_periods = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 512) stream->timer_period_frag = 0; /* reset theoretical stream pos */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 513) stream->timer_buf_periods = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 514) stream->timer_is_synced = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 515)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 516) stream_mask =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 517) stream->pipe->is_capture ? 1 : 1<<stream->substream->number;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 518)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 519) pcxhr_init_rmh(&rmh, start ? CMD_START_STREAM : CMD_STOP_STREAM);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 520) pcxhr_set_pipe_cmd_params(&rmh, stream->pipe->is_capture,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 521) stream->pipe->first_audio, 0, stream_mask);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 522)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 523) chip = snd_pcm_substream_chip(stream->substream);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 524)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 525) err = pcxhr_send_msg(chip->mgr, &rmh);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 526) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 527) dev_err(chip->card->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 528) "ERROR pcxhr_set_stream_state err=%x;\n", err);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 529) stream->status =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 530) start ? PCXHR_STREAM_STATUS_STARTED : PCXHR_STREAM_STATUS_STOPPED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 531) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 532) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 533)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 534) #define HEADER_FMT_BASE_LIN 0xfed00000
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 535) #define HEADER_FMT_BASE_FLOAT 0xfad00000
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 536) #define HEADER_FMT_INTEL 0x00008000
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 537) #define HEADER_FMT_24BITS 0x00004000
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 538) #define HEADER_FMT_16BITS 0x00002000
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 539) #define HEADER_FMT_UPTO11 0x00000200
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 540) #define HEADER_FMT_UPTO32 0x00000100
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 541) #define HEADER_FMT_MONO 0x00000080
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 542)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 543) static int pcxhr_set_format(struct pcxhr_stream *stream)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 544) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 545) int err, is_capture, sample_rate, stream_num;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 546) struct snd_pcxhr *chip;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 547) struct pcxhr_rmh rmh;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 548) unsigned int header;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 549)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 550) chip = snd_pcm_substream_chip(stream->substream);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 551) switch (stream->format) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 552) case SNDRV_PCM_FORMAT_U8:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 553) header = HEADER_FMT_BASE_LIN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 554) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 555) case SNDRV_PCM_FORMAT_S16_LE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 556) header = HEADER_FMT_BASE_LIN |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 557) HEADER_FMT_16BITS | HEADER_FMT_INTEL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 558) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 559) case SNDRV_PCM_FORMAT_S16_BE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 560) header = HEADER_FMT_BASE_LIN | HEADER_FMT_16BITS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 561) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 562) case SNDRV_PCM_FORMAT_S24_3LE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 563) header = HEADER_FMT_BASE_LIN |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 564) HEADER_FMT_24BITS | HEADER_FMT_INTEL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 565) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 566) case SNDRV_PCM_FORMAT_S24_3BE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 567) header = HEADER_FMT_BASE_LIN | HEADER_FMT_24BITS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 568) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 569) case SNDRV_PCM_FORMAT_FLOAT_LE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 570) header = HEADER_FMT_BASE_FLOAT | HEADER_FMT_INTEL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 571) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 572) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 573) dev_err(chip->card->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 574) "error pcxhr_set_format() : unknown format\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 575) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 576) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 577)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 578) sample_rate = chip->mgr->sample_rate;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 579) if (sample_rate <= 32000 && sample_rate !=0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 580) if (sample_rate <= 11025)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 581) header |= HEADER_FMT_UPTO11;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 582) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 583) header |= HEADER_FMT_UPTO32;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 584) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 585) if (stream->channels == 1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 586) header |= HEADER_FMT_MONO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 587)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 588) is_capture = stream->pipe->is_capture;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 589) stream_num = is_capture ? 0 : stream->substream->number;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 590)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 591) pcxhr_init_rmh(&rmh, is_capture ?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 592) CMD_FORMAT_STREAM_IN : CMD_FORMAT_STREAM_OUT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 593) pcxhr_set_pipe_cmd_params(&rmh, is_capture, stream->pipe->first_audio,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 594) stream_num, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 595) if (is_capture) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 596) /* bug with old dsp versions: */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 597) /* bit 12 also sets the format of the playback stream */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 598) if (DSP_EXT_CMD_SET(chip->mgr))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 599) rmh.cmd[0] |= 1<<10;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 600) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 601) rmh.cmd[0] |= 1<<12;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 602) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 603) rmh.cmd[1] = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 604) rmh.cmd_len = 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 605) if (DSP_EXT_CMD_SET(chip->mgr)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 606) /* add channels and set bit 19 if channels>2 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 607) rmh.cmd[1] = stream->channels;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 608) if (!is_capture) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 609) /* playback : add channel mask to command */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 610) rmh.cmd[2] = (stream->channels == 1) ? 0x01 : 0x03;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 611) rmh.cmd_len = 3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 612) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 613) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 614) rmh.cmd[rmh.cmd_len++] = header >> 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 615) rmh.cmd[rmh.cmd_len++] = (header & 0xff) << 16;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 616) err = pcxhr_send_msg(chip->mgr, &rmh);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 617) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 618) dev_err(chip->card->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 619) "ERROR pcxhr_set_format err=%x;\n", err);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 620) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 621) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 622)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 623) static int pcxhr_update_r_buffer(struct pcxhr_stream *stream)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 624) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 625) int err, is_capture, stream_num;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 626) struct pcxhr_rmh rmh;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 627) struct snd_pcm_substream *subs = stream->substream;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 628) struct snd_pcxhr *chip = snd_pcm_substream_chip(subs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 629)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 630) is_capture = (subs->stream == SNDRV_PCM_STREAM_CAPTURE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 631) stream_num = is_capture ? 0 : subs->number;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 632)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 633) dev_dbg(chip->card->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 634) "pcxhr_update_r_buffer(pcm%c%d) : addr(%p) bytes(%zx) subs(%d)\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 635) is_capture ? 'c' : 'p',
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 636) chip->chip_idx, (void *)(long)subs->runtime->dma_addr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 637) subs->runtime->dma_bytes, subs->number);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 638)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 639) pcxhr_init_rmh(&rmh, CMD_UPDATE_R_BUFFERS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 640) pcxhr_set_pipe_cmd_params(&rmh, is_capture, stream->pipe->first_audio,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 641) stream_num, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 642)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 643) /* max buffer size is 2 MByte */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 644) snd_BUG_ON(subs->runtime->dma_bytes >= 0x200000);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 645) /* size in bits */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 646) rmh.cmd[1] = subs->runtime->dma_bytes * 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 647) /* most significant byte */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 648) rmh.cmd[2] = subs->runtime->dma_addr >> 24;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 649) /* this is a circular buffer */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 650) rmh.cmd[2] |= 1<<19;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 651) /* least 3 significant bytes */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 652) rmh.cmd[3] = subs->runtime->dma_addr & MASK_DSP_WORD;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 653) rmh.cmd_len = 4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 654) err = pcxhr_send_msg(chip->mgr, &rmh);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 655) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 656) dev_err(chip->card->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 657) "ERROR CMD_UPDATE_R_BUFFERS err=%x;\n", err);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 658) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 659) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 660)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 661)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 662) #if 0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 663) static int pcxhr_pipe_sample_count(struct pcxhr_stream *stream,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 664) snd_pcm_uframes_t *sample_count)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 665) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 666) struct pcxhr_rmh rmh;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 667) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 668) pcxhr_t *chip = snd_pcm_substream_chip(stream->substream);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 669) pcxhr_init_rmh(&rmh, CMD_PIPE_SAMPLE_COUNT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 670) pcxhr_set_pipe_cmd_params(&rmh, stream->pipe->is_capture, 0, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 671) 1<<stream->pipe->first_audio);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 672) err = pcxhr_send_msg(chip->mgr, &rmh);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 673) if (err == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 674) *sample_count = ((snd_pcm_uframes_t)rmh.stat[0]) << 24;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 675) *sample_count += (snd_pcm_uframes_t)rmh.stat[1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 676) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 677) dev_dbg(chip->card->dev, "PIPE_SAMPLE_COUNT = %lx\n", *sample_count);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 678) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 679) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 680) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 681)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 682) static inline int pcxhr_stream_scheduled_get_pipe(struct pcxhr_stream *stream,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 683) struct pcxhr_pipe **pipe)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 684) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 685) if (stream->status == PCXHR_STREAM_STATUS_SCHEDULE_RUN) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 686) *pipe = stream->pipe;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 687) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 688) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 689) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 690) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 691)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 692) static void pcxhr_start_linked_stream(struct pcxhr_mgr *mgr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 693) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 694) int i, j, err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 695) struct pcxhr_pipe *pipe;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 696) struct snd_pcxhr *chip;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 697) int capture_mask = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 698) int playback_mask = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 699)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 700) #ifdef CONFIG_SND_DEBUG_VERBOSE
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 701) ktime_t start_time, stop_time, diff_time;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 702)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 703) start_time = ktime_get();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 704) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 705) mutex_lock(&mgr->setup_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 706)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 707) /* check the pipes concerned and build pipe_array */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 708) for (i = 0; i < mgr->num_cards; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 709) chip = mgr->chip[i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 710) for (j = 0; j < chip->nb_streams_capt; j++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 711) if (pcxhr_stream_scheduled_get_pipe(&chip->capture_stream[j], &pipe))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 712) capture_mask |= (1 << pipe->first_audio);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 713) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 714) for (j = 0; j < chip->nb_streams_play; j++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 715) if (pcxhr_stream_scheduled_get_pipe(&chip->playback_stream[j], &pipe)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 716) playback_mask |= (1 << pipe->first_audio);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 717) break; /* add only once, as all playback
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 718) * streams of one chip use the same pipe
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 719) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 720) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 721) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 722) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 723) if (capture_mask == 0 && playback_mask == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 724) mutex_unlock(&mgr->setup_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 725) dev_err(&mgr->pci->dev, "pcxhr_start_linked_stream : no pipes\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 726) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 727) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 728)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 729) dev_dbg(&mgr->pci->dev, "pcxhr_start_linked_stream : "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 730) "playback_mask=%x capture_mask=%x\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 731) playback_mask, capture_mask);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 732)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 733) /* synchronous stop of all the pipes concerned */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 734) err = pcxhr_set_pipe_state(mgr, playback_mask, capture_mask, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 735) if (err) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 736) mutex_unlock(&mgr->setup_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 737) dev_err(&mgr->pci->dev, "pcxhr_start_linked_stream : "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 738) "error stop pipes (P%x C%x)\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 739) playback_mask, capture_mask);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 740) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 741) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 742)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 743) /* the dsp lost format and buffer info with the stop pipe */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 744) for (i = 0; i < mgr->num_cards; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 745) struct pcxhr_stream *stream;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 746) chip = mgr->chip[i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 747) for (j = 0; j < chip->nb_streams_capt; j++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 748) stream = &chip->capture_stream[j];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 749) if (pcxhr_stream_scheduled_get_pipe(stream, &pipe)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 750) err = pcxhr_set_format(stream);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 751) err = pcxhr_update_r_buffer(stream);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 752) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 753) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 754) for (j = 0; j < chip->nb_streams_play; j++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 755) stream = &chip->playback_stream[j];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 756) if (pcxhr_stream_scheduled_get_pipe(stream, &pipe)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 757) err = pcxhr_set_format(stream);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 758) err = pcxhr_update_r_buffer(stream);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 759) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 760) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 761) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 762) /* start all the streams */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 763) for (i = 0; i < mgr->num_cards; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 764) struct pcxhr_stream *stream;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 765) chip = mgr->chip[i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 766) for (j = 0; j < chip->nb_streams_capt; j++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 767) stream = &chip->capture_stream[j];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 768) if (pcxhr_stream_scheduled_get_pipe(stream, &pipe))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 769) err = pcxhr_set_stream_state(chip, stream);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 770) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 771) for (j = 0; j < chip->nb_streams_play; j++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 772) stream = &chip->playback_stream[j];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 773) if (pcxhr_stream_scheduled_get_pipe(stream, &pipe))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 774) err = pcxhr_set_stream_state(chip, stream);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 775) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 776) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 777)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 778) /* synchronous start of all the pipes concerned */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 779) err = pcxhr_set_pipe_state(mgr, playback_mask, capture_mask, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 780) if (err) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 781) mutex_unlock(&mgr->setup_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 782) dev_err(&mgr->pci->dev, "pcxhr_start_linked_stream : "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 783) "error start pipes (P%x C%x)\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 784) playback_mask, capture_mask);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 785) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 786) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 787)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 788) /* put the streams into the running state now
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 789) * (increment pointer by interrupt)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 790) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 791) mutex_lock(&mgr->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 792) for ( i =0; i < mgr->num_cards; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 793) struct pcxhr_stream *stream;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 794) chip = mgr->chip[i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 795) for(j = 0; j < chip->nb_streams_capt; j++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 796) stream = &chip->capture_stream[j];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 797) if(stream->status == PCXHR_STREAM_STATUS_STARTED)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 798) stream->status = PCXHR_STREAM_STATUS_RUNNING;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 799) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 800) for (j = 0; j < chip->nb_streams_play; j++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 801) stream = &chip->playback_stream[j];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 802) if (stream->status == PCXHR_STREAM_STATUS_STARTED) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 803) /* playback will already have advanced ! */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 804) stream->timer_period_frag += mgr->granularity;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 805) stream->status = PCXHR_STREAM_STATUS_RUNNING;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 806) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 807) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 808) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 809) mutex_unlock(&mgr->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 810)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 811) mutex_unlock(&mgr->setup_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 812)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 813) #ifdef CONFIG_SND_DEBUG_VERBOSE
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 814) stop_time = ktime_get();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 815) diff_time = ktime_sub(stop_time, start_time);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 816) dev_dbg(&mgr->pci->dev, "***TRIGGER START*** TIME = %ld (err = %x)\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 817) (long)(ktime_to_ns(diff_time)), err);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 818) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 819) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 820)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 821)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 822) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 823) * trigger callback
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 824) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 825) static int pcxhr_trigger(struct snd_pcm_substream *subs, int cmd)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 826) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 827) struct pcxhr_stream *stream;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 828) struct snd_pcm_substream *s;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 829) struct snd_pcxhr *chip = snd_pcm_substream_chip(subs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 830)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 831) switch (cmd) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 832) case SNDRV_PCM_TRIGGER_START:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 833) dev_dbg(chip->card->dev, "SNDRV_PCM_TRIGGER_START\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 834) if (snd_pcm_stream_linked(subs)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 835) snd_pcm_group_for_each_entry(s, subs) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 836) if (snd_pcm_substream_chip(s) != chip)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 837) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 838) stream = s->runtime->private_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 839) stream->status =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 840) PCXHR_STREAM_STATUS_SCHEDULE_RUN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 841) snd_pcm_trigger_done(s, subs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 842) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 843) pcxhr_start_linked_stream(chip->mgr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 844) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 845) stream = subs->runtime->private_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 846) dev_dbg(chip->card->dev, "Only one Substream %c %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 847) stream->pipe->is_capture ? 'C' : 'P',
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 848) stream->pipe->first_audio);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 849) if (pcxhr_set_format(stream))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 850) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 851) if (pcxhr_update_r_buffer(stream))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 852) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 853)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 854) stream->status = PCXHR_STREAM_STATUS_SCHEDULE_RUN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 855) if (pcxhr_set_stream_state(chip, stream))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 856) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 857) stream->status = PCXHR_STREAM_STATUS_RUNNING;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 858) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 859) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 860) case SNDRV_PCM_TRIGGER_STOP:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 861) dev_dbg(chip->card->dev, "SNDRV_PCM_TRIGGER_STOP\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 862) snd_pcm_group_for_each_entry(s, subs) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 863) stream = s->runtime->private_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 864) stream->status = PCXHR_STREAM_STATUS_SCHEDULE_STOP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 865) if (pcxhr_set_stream_state(chip, stream))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 866) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 867) snd_pcm_trigger_done(s, subs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 868) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 869) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 870) case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 871) case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 872) /* TODO */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 873) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 874) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 875) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 876) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 877) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 878)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 879)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 880) static int pcxhr_hardware_timer(struct pcxhr_mgr *mgr, int start)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 881) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 882) struct pcxhr_rmh rmh;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 883) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 884)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 885) pcxhr_init_rmh(&rmh, CMD_SET_TIMER_INTERRUPT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 886) if (start) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 887) /* last dsp time invalid */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 888) mgr->dsp_time_last = PCXHR_DSP_TIME_INVALID;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 889) rmh.cmd[0] |= mgr->granularity;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 890) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 891) err = pcxhr_send_msg(mgr, &rmh);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 892) if (err < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 893) dev_err(&mgr->pci->dev, "error pcxhr_hardware_timer err(%x)\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 894) err);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 895) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 896) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 897)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 898) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 899) * prepare callback for all pcms
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 900) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 901) static int pcxhr_prepare(struct snd_pcm_substream *subs)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 902) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 903) struct snd_pcxhr *chip = snd_pcm_substream_chip(subs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 904) struct pcxhr_mgr *mgr = chip->mgr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 905) int err = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 906)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 907) dev_dbg(chip->card->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 908) "pcxhr_prepare : period_size(%lx) periods(%x) buffer_size(%lx)\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 909) subs->runtime->period_size, subs->runtime->periods,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 910) subs->runtime->buffer_size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 911)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 912) mutex_lock(&mgr->setup_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 913)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 914) do {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 915) /* only the first stream can choose the sample rate */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 916) /* set the clock only once (first stream) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 917) if (mgr->sample_rate != subs->runtime->rate) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 918) err = pcxhr_set_clock(mgr, subs->runtime->rate);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 919) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 920) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 921) if (mgr->sample_rate == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 922) /* start the DSP-timer */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 923) err = pcxhr_hardware_timer(mgr, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 924) mgr->sample_rate = subs->runtime->rate;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 925) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 926) } while(0); /* do only once (so we can use break instead of goto) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 927)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 928) mutex_unlock(&mgr->setup_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 929)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 930) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 931) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 932)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 933)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 934) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 935) * HW_PARAMS callback for all pcms
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 936) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 937) static int pcxhr_hw_params(struct snd_pcm_substream *subs,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 938) struct snd_pcm_hw_params *hw)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 939) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 940) struct snd_pcxhr *chip = snd_pcm_substream_chip(subs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 941) struct pcxhr_mgr *mgr = chip->mgr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 942) struct pcxhr_stream *stream = subs->runtime->private_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 943)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 944) mutex_lock(&mgr->setup_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 945)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 946) /* set up channels */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 947) stream->channels = params_channels(hw);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 948) /* set up format for the stream */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 949) stream->format = params_format(hw);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 950)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 951) mutex_unlock(&mgr->setup_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 952)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 953) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 954) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 955)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 956)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 957) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 958) * CONFIGURATION SPACE for all pcms, mono pcm must update channels_max
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 959) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 960) static const struct snd_pcm_hardware pcxhr_caps =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 961) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 962) .info = (SNDRV_PCM_INFO_MMAP |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 963) SNDRV_PCM_INFO_INTERLEAVED |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 964) SNDRV_PCM_INFO_MMAP_VALID |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 965) SNDRV_PCM_INFO_SYNC_START),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 966) .formats = (SNDRV_PCM_FMTBIT_U8 |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 967) SNDRV_PCM_FMTBIT_S16_LE |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 968) SNDRV_PCM_FMTBIT_S16_BE |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 969) SNDRV_PCM_FMTBIT_S24_3LE |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 970) SNDRV_PCM_FMTBIT_S24_3BE |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 971) SNDRV_PCM_FMTBIT_FLOAT_LE),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 972) .rates = (SNDRV_PCM_RATE_CONTINUOUS |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 973) SNDRV_PCM_RATE_8000_192000),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 974) .rate_min = 8000,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 975) .rate_max = 192000,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 976) .channels_min = 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 977) .channels_max = 2,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 978) .buffer_bytes_max = (32*1024),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 979) /* 1 byte == 1 frame U8 mono (PCXHR_GRANULARITY is frames!) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 980) .period_bytes_min = (2*PCXHR_GRANULARITY),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 981) .period_bytes_max = (16*1024),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 982) .periods_min = 2,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 983) .periods_max = (32*1024/PCXHR_GRANULARITY),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 984) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 985)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 986)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 987) static int pcxhr_open(struct snd_pcm_substream *subs)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 988) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 989) struct snd_pcxhr *chip = snd_pcm_substream_chip(subs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 990) struct pcxhr_mgr *mgr = chip->mgr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 991) struct snd_pcm_runtime *runtime = subs->runtime;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 992) struct pcxhr_stream *stream;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 993) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 994)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 995) mutex_lock(&mgr->setup_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 996)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 997) /* copy the struct snd_pcm_hardware struct */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 998) runtime->hw = pcxhr_caps;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 999)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1000) if( subs->stream == SNDRV_PCM_STREAM_PLAYBACK ) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1001) dev_dbg(chip->card->dev, "pcxhr_open playback chip%d subs%d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1002) chip->chip_idx, subs->number);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1003) stream = &chip->playback_stream[subs->number];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1004) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1005) dev_dbg(chip->card->dev, "pcxhr_open capture chip%d subs%d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1006) chip->chip_idx, subs->number);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1007) if (mgr->mono_capture)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1008) runtime->hw.channels_max = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1009) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1010) runtime->hw.channels_min = 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1011) stream = &chip->capture_stream[subs->number];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1012) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1013) if (stream->status != PCXHR_STREAM_STATUS_FREE){
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1014) /* streams in use */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1015) dev_err(chip->card->dev, "pcxhr_open chip%d subs%d in use\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1016) chip->chip_idx, subs->number);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1017) mutex_unlock(&mgr->setup_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1018) return -EBUSY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1019) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1020)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1021) /* float format support is in some cases buggy on stereo cards */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1022) if (mgr->is_hr_stereo)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1023) runtime->hw.formats &= ~SNDRV_PCM_FMTBIT_FLOAT_LE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1024)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1025) /* buffer-size should better be multiple of period-size */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1026) err = snd_pcm_hw_constraint_integer(runtime,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1027) SNDRV_PCM_HW_PARAM_PERIODS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1028) if (err < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1029) mutex_unlock(&mgr->setup_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1030) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1031) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1032)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1033) /* if a sample rate is already used or fixed by external clock,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1034) * the stream cannot change
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1035) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1036) if (mgr->sample_rate)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1037) runtime->hw.rate_min = runtime->hw.rate_max = mgr->sample_rate;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1038) else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1039) if (mgr->use_clock_type != PCXHR_CLOCK_TYPE_INTERNAL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1040) int external_rate;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1041) if (pcxhr_get_external_clock(mgr, mgr->use_clock_type,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1042) &external_rate) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1043) external_rate == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1044) /* cannot detect the external clock rate */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1045) mutex_unlock(&mgr->setup_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1046) return -EBUSY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1047) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1048) runtime->hw.rate_min = external_rate;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1049) runtime->hw.rate_max = external_rate;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1050) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1051) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1052)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1053) stream->status = PCXHR_STREAM_STATUS_OPEN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1054) stream->substream = subs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1055) stream->channels = 0; /* not configured yet */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1056)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1057) runtime->private_data = stream;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1058)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1059) /* better get a divisor of granularity values (96 or 192) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1060) snd_pcm_hw_constraint_step(runtime, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1061) SNDRV_PCM_HW_PARAM_BUFFER_SIZE, 32);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1062) snd_pcm_hw_constraint_step(runtime, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1063) SNDRV_PCM_HW_PARAM_PERIOD_SIZE, 32);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1064) snd_pcm_set_sync(subs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1065)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1066) mgr->ref_count_rate++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1067)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1068) mutex_unlock(&mgr->setup_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1069) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1070) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1071)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1072)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1073) static int pcxhr_close(struct snd_pcm_substream *subs)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1074) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1075) struct snd_pcxhr *chip = snd_pcm_substream_chip(subs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1076) struct pcxhr_mgr *mgr = chip->mgr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1077) struct pcxhr_stream *stream = subs->runtime->private_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1078)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1079) mutex_lock(&mgr->setup_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1080)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1081) dev_dbg(chip->card->dev, "pcxhr_close chip%d subs%d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1082) chip->chip_idx, subs->number);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1083)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1084) /* sample rate released */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1085) if (--mgr->ref_count_rate == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1086) mgr->sample_rate = 0; /* the sample rate is no more locked */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1087) pcxhr_hardware_timer(mgr, 0); /* stop the DSP-timer */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1088) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1089)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1090) stream->status = PCXHR_STREAM_STATUS_FREE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1091) stream->substream = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1092)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1093) mutex_unlock(&mgr->setup_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1094)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1095) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1096) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1097)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1098)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1099) static snd_pcm_uframes_t pcxhr_stream_pointer(struct snd_pcm_substream *subs)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1100) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1101) u_int32_t timer_period_frag;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1102) int timer_buf_periods;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1103) struct snd_pcxhr *chip = snd_pcm_substream_chip(subs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1104) struct snd_pcm_runtime *runtime = subs->runtime;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1105) struct pcxhr_stream *stream = runtime->private_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1106)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1107) mutex_lock(&chip->mgr->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1108)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1109) /* get the period fragment and the nb of periods in the buffer */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1110) timer_period_frag = stream->timer_period_frag;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1111) timer_buf_periods = stream->timer_buf_periods;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1112)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1113) mutex_unlock(&chip->mgr->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1114)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1115) return (snd_pcm_uframes_t)((timer_buf_periods * runtime->period_size) +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1116) timer_period_frag);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1117) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1118)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1119)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1120) static const struct snd_pcm_ops pcxhr_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1121) .open = pcxhr_open,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1122) .close = pcxhr_close,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1123) .prepare = pcxhr_prepare,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1124) .hw_params = pcxhr_hw_params,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1125) .trigger = pcxhr_trigger,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1126) .pointer = pcxhr_stream_pointer,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1127) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1128)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1129) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1130) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1131) int pcxhr_create_pcm(struct snd_pcxhr *chip)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1132) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1133) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1134) struct snd_pcm *pcm;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1135) char name[32];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1136)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1137) snprintf(name, sizeof(name), "pcxhr %d", chip->chip_idx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1138) if ((err = snd_pcm_new(chip->card, name, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1139) chip->nb_streams_play,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1140) chip->nb_streams_capt, &pcm)) < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1141) dev_err(chip->card->dev, "cannot create pcm %s\n", name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1142) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1143) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1144) pcm->private_data = chip;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1145)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1146) if (chip->nb_streams_play)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1147) snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &pcxhr_ops);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1148) if (chip->nb_streams_capt)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1149) snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &pcxhr_ops);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1150)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1151) pcm->info_flags = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1152) pcm->nonatomic = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1153) strcpy(pcm->name, name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1154)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1155) snd_pcm_set_managed_buffer_all(pcm, SNDRV_DMA_TYPE_DEV,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1156) &chip->mgr->pci->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1157) 32*1024, 32*1024);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1158) chip->pcm = pcm;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1159) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1160) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1161)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1162) static int pcxhr_chip_free(struct snd_pcxhr *chip)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1163) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1164) kfree(chip);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1165) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1166) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1167)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1168) static int pcxhr_chip_dev_free(struct snd_device *device)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1169) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1170) struct snd_pcxhr *chip = device->device_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1171) return pcxhr_chip_free(chip);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1172) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1173)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1174)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1175) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1176) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1177) static int pcxhr_create(struct pcxhr_mgr *mgr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1178) struct snd_card *card, int idx)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1179) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1180) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1181) struct snd_pcxhr *chip;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1182) static const struct snd_device_ops ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1183) .dev_free = pcxhr_chip_dev_free,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1184) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1185)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1186) chip = kzalloc(sizeof(*chip), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1187) if (!chip)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1188) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1189)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1190) chip->card = card;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1191) chip->chip_idx = idx;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1192) chip->mgr = mgr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1193) card->sync_irq = mgr->irq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1194)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1195) if (idx < mgr->playback_chips)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1196) /* stereo or mono streams */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1197) chip->nb_streams_play = PCXHR_PLAYBACK_STREAMS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1198)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1199) if (idx < mgr->capture_chips) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1200) if (mgr->mono_capture)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1201) chip->nb_streams_capt = 2; /* 2 mono streams */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1202) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1203) chip->nb_streams_capt = 1; /* or 1 stereo stream */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1204) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1205)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1206) if ((err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, chip, &ops)) < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1207) pcxhr_chip_free(chip);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1208) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1209) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1210)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1211) mgr->chip[idx] = chip;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1212)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1213) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1214) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1215)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1216) /* proc interface */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1217) static void pcxhr_proc_info(struct snd_info_entry *entry,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1218) struct snd_info_buffer *buffer)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1219) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1220) struct snd_pcxhr *chip = entry->private_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1221) struct pcxhr_mgr *mgr = chip->mgr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1222)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1223) snd_iprintf(buffer, "\n%s\n", mgr->name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1224)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1225) /* stats available when embedded DSP is running */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1226) if (mgr->dsp_loaded & (1 << PCXHR_FIRMWARE_DSP_MAIN_INDEX)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1227) struct pcxhr_rmh rmh;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1228) short ver_maj = (mgr->dsp_version >> 16) & 0xff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1229) short ver_min = (mgr->dsp_version >> 8) & 0xff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1230) short ver_build = mgr->dsp_version & 0xff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1231) snd_iprintf(buffer, "module version %s\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1232) PCXHR_DRIVER_VERSION_STRING);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1233) snd_iprintf(buffer, "dsp version %d.%d.%d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1234) ver_maj, ver_min, ver_build);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1235) if (mgr->board_has_analog)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1236) snd_iprintf(buffer, "analog io available\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1237) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1238) snd_iprintf(buffer, "digital only board\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1239)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1240) /* calc cpu load of the dsp */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1241) pcxhr_init_rmh(&rmh, CMD_GET_DSP_RESOURCES);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1242) if( ! pcxhr_send_msg(mgr, &rmh) ) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1243) int cur = rmh.stat[0];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1244) int ref = rmh.stat[1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1245) if (ref > 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1246) if (mgr->sample_rate_real != 0 &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1247) mgr->sample_rate_real != 48000) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1248) ref = (ref * 48000) /
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1249) mgr->sample_rate_real;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1250) if (mgr->sample_rate_real >=
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1251) PCXHR_IRQ_TIMER_FREQ)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1252) ref *= 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1253) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1254) cur = 100 - (100 * cur) / ref;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1255) snd_iprintf(buffer, "cpu load %d%%\n", cur);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1256) snd_iprintf(buffer, "buffer pool %d/%d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1257) rmh.stat[2], rmh.stat[3]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1258) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1259) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1260) snd_iprintf(buffer, "dma granularity : %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1261) mgr->granularity);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1262) snd_iprintf(buffer, "dsp time errors : %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1263) mgr->dsp_time_err);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1264) snd_iprintf(buffer, "dsp async pipe xrun errors : %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1265) mgr->async_err_pipe_xrun);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1266) snd_iprintf(buffer, "dsp async stream xrun errors : %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1267) mgr->async_err_stream_xrun);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1268) snd_iprintf(buffer, "dsp async last other error : %x\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1269) mgr->async_err_other_last);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1270) /* debug zone dsp */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1271) rmh.cmd[0] = 0x4200 + PCXHR_SIZE_MAX_STATUS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1272) rmh.cmd_len = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1273) rmh.stat_len = PCXHR_SIZE_MAX_STATUS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1274) rmh.dsp_stat = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1275) rmh.cmd_idx = CMD_LAST_INDEX;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1276) if( ! pcxhr_send_msg(mgr, &rmh) ) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1277) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1278) if (rmh.stat_len > 8)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1279) rmh.stat_len = 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1280) for (i = 0; i < rmh.stat_len; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1281) snd_iprintf(buffer, "debug[%02d] = %06x\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1282) i, rmh.stat[i]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1283) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1284) } else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1285) snd_iprintf(buffer, "no firmware loaded\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1286) snd_iprintf(buffer, "\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1287) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1288) static void pcxhr_proc_sync(struct snd_info_entry *entry,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1289) struct snd_info_buffer *buffer)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1290) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1291) struct snd_pcxhr *chip = entry->private_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1292) struct pcxhr_mgr *mgr = chip->mgr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1293) static const char *textsHR22[3] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1294) "Internal", "AES Sync", "AES 1"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1295) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1296) static const char *textsPCXHR[7] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1297) "Internal", "Word", "AES Sync",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1298) "AES 1", "AES 2", "AES 3", "AES 4"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1299) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1300) const char **texts;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1301) int max_clock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1302) if (mgr->is_hr_stereo) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1303) texts = textsHR22;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1304) max_clock = HR22_CLOCK_TYPE_MAX;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1305) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1306) texts = textsPCXHR;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1307) max_clock = PCXHR_CLOCK_TYPE_MAX;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1308) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1309)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1310) snd_iprintf(buffer, "\n%s\n", mgr->name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1311) snd_iprintf(buffer, "Current Sample Clock\t: %s\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1312) texts[mgr->cur_clock_type]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1313) snd_iprintf(buffer, "Current Sample Rate\t= %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1314) mgr->sample_rate_real);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1315) /* commands available when embedded DSP is running */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1316) if (mgr->dsp_loaded & (1 << PCXHR_FIRMWARE_DSP_MAIN_INDEX)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1317) int i, err, sample_rate;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1318) for (i = 1; i <= max_clock; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1319) err = pcxhr_get_external_clock(mgr, i, &sample_rate);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1320) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1321) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1322) snd_iprintf(buffer, "%s Clock\t\t= %d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1323) texts[i], sample_rate);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1324) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1325) } else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1326) snd_iprintf(buffer, "no firmware loaded\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1327) snd_iprintf(buffer, "\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1328) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1329)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1330) static void pcxhr_proc_gpio_read(struct snd_info_entry *entry,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1331) struct snd_info_buffer *buffer)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1332) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1333) struct snd_pcxhr *chip = entry->private_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1334) struct pcxhr_mgr *mgr = chip->mgr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1335) /* commands available when embedded DSP is running */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1336) if (mgr->dsp_loaded & (1 << PCXHR_FIRMWARE_DSP_MAIN_INDEX)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1337) /* gpio ports on stereo boards only available */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1338) int value = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1339) hr222_read_gpio(mgr, 1, &value); /* GPI */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1340) snd_iprintf(buffer, "GPI: 0x%x\n", value);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1341) hr222_read_gpio(mgr, 0, &value); /* GP0 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1342) snd_iprintf(buffer, "GPO: 0x%x\n", value);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1343) } else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1344) snd_iprintf(buffer, "no firmware loaded\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1345) snd_iprintf(buffer, "\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1346) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1347) static void pcxhr_proc_gpo_write(struct snd_info_entry *entry,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1348) struct snd_info_buffer *buffer)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1349) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1350) struct snd_pcxhr *chip = entry->private_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1351) struct pcxhr_mgr *mgr = chip->mgr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1352) char line[64];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1353) int value;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1354) /* commands available when embedded DSP is running */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1355) if (!(mgr->dsp_loaded & (1 << PCXHR_FIRMWARE_DSP_MAIN_INDEX)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1356) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1357) while (!snd_info_get_line(buffer, line, sizeof(line))) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1358) if (sscanf(line, "GPO: 0x%x", &value) != 1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1359) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1360) hr222_write_gpo(mgr, value); /* GP0 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1361) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1362) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1363)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1364) /* Access to the results of the CMD_GET_TIME_CODE RMH */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1365) #define TIME_CODE_VALID_MASK 0x00800000
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1366) #define TIME_CODE_NEW_MASK 0x00400000
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1367) #define TIME_CODE_BACK_MASK 0x00200000
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1368) #define TIME_CODE_WAIT_MASK 0x00100000
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1369)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1370) /* Values for the CMD_MANAGE_SIGNAL RMH */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1371) #define MANAGE_SIGNAL_TIME_CODE 0x01
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1372) #define MANAGE_SIGNAL_MIDI 0x02
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1373)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1374) /* linear time code read proc*/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1375) static void pcxhr_proc_ltc(struct snd_info_entry *entry,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1376) struct snd_info_buffer *buffer)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1377) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1378) struct snd_pcxhr *chip = entry->private_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1379) struct pcxhr_mgr *mgr = chip->mgr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1380) struct pcxhr_rmh rmh;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1381) unsigned int ltcHrs, ltcMin, ltcSec, ltcFrm;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1382) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1383) /* commands available when embedded DSP is running */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1384) if (!(mgr->dsp_loaded & (1 << PCXHR_FIRMWARE_DSP_MAIN_INDEX))) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1385) snd_iprintf(buffer, "no firmware loaded\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1386) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1387) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1388) if (!mgr->capture_ltc) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1389) pcxhr_init_rmh(&rmh, CMD_MANAGE_SIGNAL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1390) rmh.cmd[0] |= MANAGE_SIGNAL_TIME_CODE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1391) err = pcxhr_send_msg(mgr, &rmh);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1392) if (err) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1393) snd_iprintf(buffer, "ltc not activated (%d)\n", err);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1394) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1395) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1396) if (mgr->is_hr_stereo)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1397) hr222_manage_timecode(mgr, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1398) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1399) pcxhr_write_io_num_reg_cont(mgr, REG_CONT_VALSMPTE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1400) REG_CONT_VALSMPTE, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1401) mgr->capture_ltc = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1402) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1403) pcxhr_init_rmh(&rmh, CMD_GET_TIME_CODE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1404) err = pcxhr_send_msg(mgr, &rmh);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1405) if (err) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1406) snd_iprintf(buffer, "ltc read error (err=%d)\n", err);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1407) return ;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1408) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1409) ltcHrs = 10*((rmh.stat[0] >> 8) & 0x3) + (rmh.stat[0] & 0xf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1410) ltcMin = 10*((rmh.stat[1] >> 16) & 0x7) + ((rmh.stat[1] >> 8) & 0xf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1411) ltcSec = 10*(rmh.stat[1] & 0x7) + ((rmh.stat[2] >> 16) & 0xf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1412) ltcFrm = 10*((rmh.stat[2] >> 8) & 0x3) + (rmh.stat[2] & 0xf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1413)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1414) snd_iprintf(buffer, "timecode: %02u:%02u:%02u-%02u\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1415) ltcHrs, ltcMin, ltcSec, ltcFrm);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1416) snd_iprintf(buffer, "raw: 0x%04x%06x%06x\n", rmh.stat[0] & 0x00ffff,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1417) rmh.stat[1] & 0xffffff, rmh.stat[2] & 0xffffff);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1418) /*snd_iprintf(buffer, "dsp ref time: 0x%06x%06x\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1419) rmh.stat[3] & 0xffffff, rmh.stat[4] & 0xffffff);*/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1420) if (!(rmh.stat[0] & TIME_CODE_VALID_MASK)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1421) snd_iprintf(buffer, "warning: linear timecode not valid\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1422) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1423) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1424)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1425) static void pcxhr_proc_init(struct snd_pcxhr *chip)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1426) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1427) snd_card_ro_proc_new(chip->card, "info", chip, pcxhr_proc_info);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1428) snd_card_ro_proc_new(chip->card, "sync", chip, pcxhr_proc_sync);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1429) /* gpio available on stereo sound cards only */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1430) if (chip->mgr->is_hr_stereo)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1431) snd_card_rw_proc_new(chip->card, "gpio", chip,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1432) pcxhr_proc_gpio_read,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1433) pcxhr_proc_gpo_write);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1434) snd_card_ro_proc_new(chip->card, "ltc", chip, pcxhr_proc_ltc);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1435) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1436) /* end of proc interface */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1437)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1438) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1439) * release all the cards assigned to a manager instance
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1440) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1441) static int pcxhr_free(struct pcxhr_mgr *mgr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1442) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1443) unsigned int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1444)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1445) for (i = 0; i < mgr->num_cards; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1446) if (mgr->chip[i])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1447) snd_card_free(mgr->chip[i]->card);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1448) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1449)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1450) /* reset board if some firmware was loaded */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1451) if(mgr->dsp_loaded) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1452) pcxhr_reset_board(mgr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1453) dev_dbg(&mgr->pci->dev, "reset pcxhr !\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1454) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1455)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1456) /* release irq */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1457) if (mgr->irq >= 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1458) free_irq(mgr->irq, mgr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1459)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1460) pci_release_regions(mgr->pci);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1461)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1462) /* free hostport purgebuffer */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1463) if (mgr->hostport.area) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1464) snd_dma_free_pages(&mgr->hostport);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1465) mgr->hostport.area = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1466) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1467)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1468) kfree(mgr->prmh);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1469)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1470) pci_disable_device(mgr->pci);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1471) kfree(mgr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1472) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1473) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1474)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1475) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1476) * probe function - creates the card manager
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1477) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1478) static int pcxhr_probe(struct pci_dev *pci,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1479) const struct pci_device_id *pci_id)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1480) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1481) static int dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1482) struct pcxhr_mgr *mgr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1483) unsigned int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1484) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1485) size_t size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1486) char *card_name;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1487)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1488) if (dev >= SNDRV_CARDS)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1489) return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1490) if (! enable[dev]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1491) dev++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1492) return -ENOENT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1493) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1494)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1495) /* enable PCI device */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1496) if ((err = pci_enable_device(pci)) < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1497) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1498) pci_set_master(pci);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1499)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1500) /* check if we can restrict PCI DMA transfers to 32 bits */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1501) if (dma_set_mask(&pci->dev, DMA_BIT_MASK(32)) < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1502) dev_err(&pci->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1503) "architecture does not support 32bit PCI busmaster DMA\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1504) pci_disable_device(pci);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1505) return -ENXIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1506) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1507)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1508) /* alloc card manager */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1509) mgr = kzalloc(sizeof(*mgr), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1510) if (! mgr) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1511) pci_disable_device(pci);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1512) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1513) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1514)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1515) if (snd_BUG_ON(pci_id->driver_data >= PCI_ID_LAST)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1516) kfree(mgr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1517) pci_disable_device(pci);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1518) return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1519) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1520) card_name =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1521) pcxhr_board_params[pci_id->driver_data].board_name;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1522) mgr->playback_chips =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1523) pcxhr_board_params[pci_id->driver_data].playback_chips;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1524) mgr->capture_chips =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1525) pcxhr_board_params[pci_id->driver_data].capture_chips;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1526) mgr->fw_file_set =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1527) pcxhr_board_params[pci_id->driver_data].fw_file_set;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1528) mgr->firmware_num =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1529) pcxhr_board_params[pci_id->driver_data].firmware_num;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1530) mgr->mono_capture = mono[dev];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1531) mgr->is_hr_stereo = (mgr->playback_chips == 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1532) mgr->board_has_aes1 = PCXHR_BOARD_HAS_AES1(mgr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1533) mgr->board_aes_in_192k = !PCXHR_BOARD_AESIN_NO_192K(mgr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1534)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1535) if (mgr->is_hr_stereo)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1536) mgr->granularity = PCXHR_GRANULARITY_HR22;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1537) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1538) mgr->granularity = PCXHR_GRANULARITY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1539)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1540) /* resource assignment */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1541) if ((err = pci_request_regions(pci, card_name)) < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1542) kfree(mgr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1543) pci_disable_device(pci);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1544) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1545) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1546) for (i = 0; i < 3; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1547) mgr->port[i] = pci_resource_start(pci, i);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1548)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1549) mgr->pci = pci;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1550) mgr->irq = -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1551)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1552) if (request_threaded_irq(pci->irq, pcxhr_interrupt,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1553) pcxhr_threaded_irq, IRQF_SHARED,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1554) KBUILD_MODNAME, mgr)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1555) dev_err(&pci->dev, "unable to grab IRQ %d\n", pci->irq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1556) pcxhr_free(mgr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1557) return -EBUSY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1558) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1559) mgr->irq = pci->irq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1560)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1561) snprintf(mgr->name, sizeof(mgr->name),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1562) "Digigram at 0x%lx & 0x%lx, 0x%lx irq %i",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1563) mgr->port[0], mgr->port[1], mgr->port[2], mgr->irq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1564)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1565) /* ISR lock */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1566) mutex_init(&mgr->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1567) mutex_init(&mgr->msg_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1568)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1569) /* init setup mutex*/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1570) mutex_init(&mgr->setup_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1571)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1572) mgr->prmh = kmalloc(sizeof(*mgr->prmh) +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1573) sizeof(u32) * (PCXHR_SIZE_MAX_LONG_STATUS -
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1574) PCXHR_SIZE_MAX_STATUS),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1575) GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1576) if (! mgr->prmh) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1577) pcxhr_free(mgr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1578) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1579) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1580)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1581) for (i=0; i < PCXHR_MAX_CARDS; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1582) struct snd_card *card;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1583) char tmpid[16];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1584) int idx;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1585)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1586) if (i >= max(mgr->playback_chips, mgr->capture_chips))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1587) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1588) mgr->num_cards++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1589)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1590) if (index[dev] < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1591) idx = index[dev];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1592) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1593) idx = index[dev] + i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1594)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1595) snprintf(tmpid, sizeof(tmpid), "%s-%d",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1596) id[dev] ? id[dev] : card_name, i);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1597) err = snd_card_new(&pci->dev, idx, tmpid, THIS_MODULE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1598) 0, &card);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1599)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1600) if (err < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1601) dev_err(&pci->dev, "cannot allocate the card %d\n", i);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1602) pcxhr_free(mgr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1603) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1604) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1605)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1606) strcpy(card->driver, DRIVER_NAME);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1607) snprintf(card->shortname, sizeof(card->shortname),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1608) "Digigram [PCM #%d]", i);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1609) snprintf(card->longname, sizeof(card->longname),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1610) "%s [PCM #%d]", mgr->name, i);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1611)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1612) if ((err = pcxhr_create(mgr, card, i)) < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1613) snd_card_free(card);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1614) pcxhr_free(mgr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1615) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1616) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1617)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1618) if (i == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1619) /* init proc interface only for chip0 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1620) pcxhr_proc_init(mgr->chip[i]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1621)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1622) if ((err = snd_card_register(card)) < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1623) pcxhr_free(mgr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1624) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1625) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1626) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1627)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1628) /* create hostport purgebuffer */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1629) size = PAGE_ALIGN(sizeof(struct pcxhr_hostport));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1630) if (snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, &pci->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1631) size, &mgr->hostport) < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1632) pcxhr_free(mgr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1633) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1634) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1635) /* init purgebuffer */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1636) memset(mgr->hostport.area, 0, size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1637)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1638) /* create a DSP loader */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1639) err = pcxhr_setup_firmware(mgr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1640) if (err < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1641) pcxhr_free(mgr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1642) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1643) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1644)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1645) pci_set_drvdata(pci, mgr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1646) dev++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1647) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1648) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1649)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1650) static void pcxhr_remove(struct pci_dev *pci)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1651) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1652) pcxhr_free(pci_get_drvdata(pci));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1653) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1654)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1655) static struct pci_driver pcxhr_driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1656) .name = KBUILD_MODNAME,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1657) .id_table = pcxhr_ids,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1658) .probe = pcxhr_probe,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1659) .remove = pcxhr_remove,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1660) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1661)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1662) module_pci_driver(pcxhr_driver);