^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 miXart 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) 2003 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/pci.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) #include <linux/dma-mapping.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) #include <linux/module.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) #include <linux/mutex.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) #include <linux/slab.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) #include <sound/core.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) #include <sound/initval.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) #include <sound/info.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) #include <sound/control.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) #include <sound/pcm.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) #include <sound/pcm_params.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) #include "mixart.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) #include "mixart_hwdep.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) #include "mixart_core.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) #include "mixart_mixer.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) #define CARD_NAME "miXart"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) MODULE_AUTHOR("Digigram <alsa@digigram.com>");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) MODULE_DESCRIPTION("Digigram " CARD_NAME);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) MODULE_LICENSE("GPL");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) MODULE_SUPPORTED_DEVICE("{{Digigram," CARD_NAME "}}");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; /* Index 0-MAX */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; /* ID for this card */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) static bool enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP; /* Enable this card */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) module_param_array(index, int, NULL, 0444);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) MODULE_PARM_DESC(index, "Index value for Digigram " CARD_NAME " soundcard.");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) module_param_array(id, charp, NULL, 0444);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) MODULE_PARM_DESC(id, "ID string for Digigram " CARD_NAME " soundcard.");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) module_param_array(enable, bool, NULL, 0444);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) MODULE_PARM_DESC(enable, "Enable Digigram " CARD_NAME " soundcard.");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) static const struct pci_device_id snd_mixart_ids[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) { PCI_VDEVICE(MOTOROLA, 0x0003), 0, }, /* MC8240 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) { 0, }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) MODULE_DEVICE_TABLE(pci, snd_mixart_ids);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) static int mixart_set_pipe_state(struct mixart_mgr *mgr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) struct mixart_pipe *pipe, int start)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) struct mixart_group_state_req group_state;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) struct mixart_group_state_resp group_state_resp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) struct mixart_msg request;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) u32 system_msg_uid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) switch(pipe->status) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) case PIPE_RUNNING:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) case PIPE_CLOCK_SET:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) if(start) return 0; /* already started */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) case PIPE_STOPPED:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) if(!start) return 0; /* already stopped */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) dev_err(&mgr->pci->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) "error mixart_set_pipe_state called with wrong pipe->status!\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) return -EINVAL; /* function called with wrong pipe status */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) system_msg_uid = 0x12345678; /* the event ! (take care: the MSB and two LSB's have to be 0) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) /* wait on the last MSG_SYSTEM_SEND_SYNCHRO_CMD command to be really finished */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) request.message_id = MSG_SYSTEM_WAIT_SYNCHRO_CMD;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) request.uid = (struct mixart_uid){0,0};
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) request.data = &system_msg_uid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) request.size = sizeof(system_msg_uid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) err = snd_mixart_send_msg_wait_notif(mgr, &request, system_msg_uid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) if(err) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) dev_err(&mgr->pci->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) "error : MSG_SYSTEM_WAIT_SYNCHRO_CMD was not notified !\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) /* start or stop the pipe (1 pipe) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) memset(&group_state, 0, sizeof(group_state));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) group_state.pipe_count = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) group_state.pipe_uid[0] = pipe->group_uid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) if(start)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) request.message_id = MSG_STREAM_START_STREAM_GRP_PACKET;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) request.message_id = MSG_STREAM_STOP_STREAM_GRP_PACKET;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) request.uid = pipe->group_uid; /*(struct mixart_uid){0,0};*/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) request.data = &group_state;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) request.size = sizeof(group_state);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) err = snd_mixart_send_msg(mgr, &request, sizeof(group_state_resp), &group_state_resp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) if (err < 0 || group_state_resp.txx_status != 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) dev_err(&mgr->pci->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) "error MSG_STREAM_ST***_STREAM_GRP_PACKET err=%x stat=%x !\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) err, group_state_resp.txx_status);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) if(start) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) u32 stat = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) group_state.pipe_count = 0; /* in case of start same command once again with pipe_count=0 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) err = snd_mixart_send_msg(mgr, &request, sizeof(group_state_resp), &group_state_resp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) if (err < 0 || group_state_resp.txx_status != 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) dev_err(&mgr->pci->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) "error MSG_STREAM_START_STREAM_GRP_PACKET err=%x stat=%x !\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) err, group_state_resp.txx_status);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) /* in case of start send a synchro top */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) request.message_id = MSG_SYSTEM_SEND_SYNCHRO_CMD;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) request.uid = (struct mixart_uid){0,0};
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) request.data = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) request.size = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) err = snd_mixart_send_msg(mgr, &request, sizeof(stat), &stat);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) if (err < 0 || stat != 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) dev_err(&mgr->pci->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) "error MSG_SYSTEM_SEND_SYNCHRO_CMD err=%x stat=%x !\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) err, stat);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) pipe->status = PIPE_RUNNING;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) else /* !start */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) pipe->status = PIPE_STOPPED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) static int mixart_set_clock(struct mixart_mgr *mgr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) struct mixart_pipe *pipe, unsigned int rate)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) struct mixart_msg request;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) struct mixart_clock_properties clock_properties;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) struct mixart_clock_properties_resp clock_prop_resp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) switch(pipe->status) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) case PIPE_CLOCK_SET:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) case PIPE_RUNNING:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) if(rate != 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) fallthrough;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) if(rate == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) return 0; /* nothing to do */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) dev_err(&mgr->pci->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) "error mixart_set_clock(%d) called with wrong pipe->status !\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) rate);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) memset(&clock_properties, 0, sizeof(clock_properties));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) clock_properties.clock_generic_type = (rate != 0) ? CGT_INTERNAL_CLOCK : CGT_NO_CLOCK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) clock_properties.clock_mode = CM_STANDALONE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) clock_properties.frequency = rate;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) clock_properties.nb_callers = 1; /* only one entry in uid_caller ! */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) clock_properties.uid_caller[0] = pipe->group_uid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) dev_dbg(&mgr->pci->dev, "mixart_set_clock to %d kHz\n", rate);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) request.message_id = MSG_CLOCK_SET_PROPERTIES;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) request.uid = mgr->uid_console_manager;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) request.data = &clock_properties;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) request.size = sizeof(clock_properties);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) err = snd_mixart_send_msg(mgr, &request, sizeof(clock_prop_resp), &clock_prop_resp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) if (err < 0 || clock_prop_resp.status != 0 || clock_prop_resp.clock_mode != CM_STANDALONE) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) dev_err(&mgr->pci->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) "error MSG_CLOCK_SET_PROPERTIES err=%x stat=%x mod=%x !\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) err, clock_prop_resp.status, clock_prop_resp.clock_mode);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) if(rate) pipe->status = PIPE_CLOCK_SET;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) else pipe->status = PIPE_RUNNING;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) * Allocate or reference output pipe for analog IOs (pcmp0/1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) struct mixart_pipe *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) snd_mixart_add_ref_pipe(struct snd_mixart *chip, int pcm_number, int capture,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) int monitoring)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) int stream_count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) struct mixart_pipe *pipe;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) struct mixart_msg request;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) if(capture) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) if (pcm_number == MIXART_PCM_ANALOG) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) pipe = &(chip->pipe_in_ana); /* analog inputs */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) pipe = &(chip->pipe_in_dig); /* digital inputs */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) request.message_id = MSG_STREAM_ADD_OUTPUT_GROUP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) stream_count = MIXART_CAPTURE_STREAMS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) if (pcm_number == MIXART_PCM_ANALOG) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) pipe = &(chip->pipe_out_ana); /* analog outputs */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) pipe = &(chip->pipe_out_dig); /* digital outputs */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) request.message_id = MSG_STREAM_ADD_INPUT_GROUP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) stream_count = MIXART_PLAYBACK_STREAMS;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) /* a new stream is opened and there are already all streams in use */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) if( (monitoring == 0) && (pipe->references >= stream_count) ) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) /* pipe is not yet defined */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) if( pipe->status == PIPE_UNDEFINED ) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) int err, i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) struct {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) struct mixart_streaming_group_req sgroup_req;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) struct mixart_streaming_group sgroup_resp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) } *buf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) dev_dbg(chip->card->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) "add_ref_pipe audio chip(%d) pcm(%d)\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) chip->chip_idx, pcm_number);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) buf = kmalloc(sizeof(*buf), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) if (!buf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) request.uid = (struct mixart_uid){0,0}; /* should be StreamManagerUID, but zero is OK if there is only one ! */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) request.data = &buf->sgroup_req;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) request.size = sizeof(buf->sgroup_req);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) memset(&buf->sgroup_req, 0, sizeof(buf->sgroup_req));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) buf->sgroup_req.stream_count = stream_count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) buf->sgroup_req.channel_count = 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) buf->sgroup_req.latency = 256;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) buf->sgroup_req.connector = pipe->uid_left_connector; /* the left connector */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) for (i=0; i<stream_count; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) int j;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) struct mixart_flowinfo *flowinfo;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) struct mixart_bufferinfo *bufferinfo;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) /* we don't yet know the format, so config 16 bit pcm audio for instance */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) buf->sgroup_req.stream_info[i].size_max_byte_frame = 1024;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) buf->sgroup_req.stream_info[i].size_max_sample_frame = 256;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) buf->sgroup_req.stream_info[i].nb_bytes_max_per_sample = MIXART_FLOAT_P__4_0_TO_HEX; /* is 4.0f */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) /* find the right bufferinfo_array */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) j = (chip->chip_idx * MIXART_MAX_STREAM_PER_CARD) + (pcm_number * (MIXART_PLAYBACK_STREAMS + MIXART_CAPTURE_STREAMS)) + i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) if(capture) j += MIXART_PLAYBACK_STREAMS; /* in the array capture is behind playback */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) buf->sgroup_req.flow_entry[i] = j;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) flowinfo = (struct mixart_flowinfo *)chip->mgr->flowinfo.area;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) flowinfo[j].bufferinfo_array_phy_address = (u32)chip->mgr->bufferinfo.addr + (j * sizeof(struct mixart_bufferinfo));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) flowinfo[j].bufferinfo_count = 1; /* 1 will set the miXart to ring-buffer mode ! */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) bufferinfo = (struct mixart_bufferinfo *)chip->mgr->bufferinfo.area;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) bufferinfo[j].buffer_address = 0; /* buffer is not yet allocated */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) bufferinfo[j].available_length = 0; /* buffer is not yet allocated */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) /* construct the identifier of the stream buffer received in the interrupts ! */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) bufferinfo[j].buffer_id = (chip->chip_idx << MIXART_NOTIFY_CARD_OFFSET) + (pcm_number << MIXART_NOTIFY_PCM_OFFSET ) + i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) if(capture) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) bufferinfo[j].buffer_id |= MIXART_NOTIFY_CAPT_MASK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) err = snd_mixart_send_msg(chip->mgr, &request, sizeof(buf->sgroup_resp), &buf->sgroup_resp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) if((err < 0) || (buf->sgroup_resp.status != 0)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) dev_err(chip->card->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) "error MSG_STREAM_ADD_**PUT_GROUP err=%x stat=%x !\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) err, buf->sgroup_resp.status);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) kfree(buf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) pipe->group_uid = buf->sgroup_resp.group; /* id of the pipe, as returned by embedded */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) pipe->stream_count = buf->sgroup_resp.stream_count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) /* pipe->stream_uid[i] = buf->sgroup_resp.stream[i].stream_uid; */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) pipe->status = PIPE_STOPPED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) kfree(buf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) if(monitoring) pipe->monitoring = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) else pipe->references++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) return pipe;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) int snd_mixart_kill_ref_pipe(struct mixart_mgr *mgr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) struct mixart_pipe *pipe, int monitoring)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) int err = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) if(pipe->status == PIPE_UNDEFINED)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) if(monitoring)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) pipe->monitoring = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) pipe->references--;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) if((pipe->references <= 0) && (pipe->monitoring == 0)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344) struct mixart_msg request;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345) struct mixart_delete_group_resp delete_resp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347) /* release the clock */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348) err = mixart_set_clock( mgr, pipe, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349) if( err < 0 ) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350) dev_err(&mgr->pci->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351) "mixart_set_clock(0) return error!\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354) /* stop the pipe */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355) err = mixart_set_pipe_state(mgr, pipe, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356) if( err < 0 ) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357) dev_err(&mgr->pci->dev, "error stopping pipe!\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360) request.message_id = MSG_STREAM_DELETE_GROUP;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361) request.uid = (struct mixart_uid){0,0};
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362) request.data = &pipe->group_uid; /* the streaming group ! */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363) request.size = sizeof(pipe->group_uid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365) /* delete the pipe */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366) err = snd_mixart_send_msg(mgr, &request, sizeof(delete_resp), &delete_resp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367) if ((err < 0) || (delete_resp.status != 0)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368) dev_err(&mgr->pci->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369) "error MSG_STREAM_DELETE_GROUP err(%x), status(%x)\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370) err, delete_resp.status);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373) pipe->group_uid = (struct mixart_uid){0,0};
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374) pipe->stream_count = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375) pipe->status = PIPE_UNDEFINED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381) static int mixart_set_stream_state(struct mixart_stream *stream, int start)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383) struct snd_mixart *chip;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384) struct mixart_stream_state_req stream_state_req;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385) struct mixart_msg request;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387) if(!stream->substream)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390) memset(&stream_state_req, 0, sizeof(stream_state_req));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391) stream_state_req.stream_count = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392) stream_state_req.stream_info.stream_desc.uid_pipe = stream->pipe->group_uid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393) stream_state_req.stream_info.stream_desc.stream_idx = stream->substream->number;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395) if (stream->substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396) request.message_id = start ? MSG_STREAM_START_INPUT_STAGE_PACKET : MSG_STREAM_STOP_INPUT_STAGE_PACKET;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398) request.message_id = start ? MSG_STREAM_START_OUTPUT_STAGE_PACKET : MSG_STREAM_STOP_OUTPUT_STAGE_PACKET;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400) request.uid = (struct mixart_uid){0,0};
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401) request.data = &stream_state_req;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402) request.size = sizeof(stream_state_req);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404) stream->abs_period_elapsed = 0; /* reset stream pos */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405) stream->buf_periods = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406) stream->buf_period_frag = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 407)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 408) chip = snd_pcm_substream_chip(stream->substream);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 409)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 410) return snd_mixart_send_msg_nonblock(chip->mgr, &request);
^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) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 414) * Trigger callback
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 415) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 416)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 417) static int snd_mixart_trigger(struct snd_pcm_substream *subs, int cmd)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 418) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 419) struct mixart_stream *stream = subs->runtime->private_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 420)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 421) switch (cmd) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 422) case SNDRV_PCM_TRIGGER_START:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 423)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 424) dev_dbg(subs->pcm->card->dev, "SNDRV_PCM_TRIGGER_START\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 425)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 426) /* START_STREAM */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 427) if( mixart_set_stream_state(stream, 1) )
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 428) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 429)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 430) stream->status = MIXART_STREAM_STATUS_RUNNING;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 431)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 432) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 433) case SNDRV_PCM_TRIGGER_STOP:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 434)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 435) /* STOP_STREAM */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 436) if( mixart_set_stream_state(stream, 0) )
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 437) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 438)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 439) stream->status = MIXART_STREAM_STATUS_OPEN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 440)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 441) dev_dbg(subs->pcm->card->dev, "SNDRV_PCM_TRIGGER_STOP\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 442)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 443) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 444)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 445) case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 446) /* TODO */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 447) stream->status = MIXART_STREAM_STATUS_PAUSE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 448) dev_dbg(subs->pcm->card->dev, "SNDRV_PCM_PAUSE_PUSH\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 449) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 450) case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 451) /* TODO */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 452) stream->status = MIXART_STREAM_STATUS_RUNNING;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 453) dev_dbg(subs->pcm->card->dev, "SNDRV_PCM_PAUSE_RELEASE\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 454) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 455) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 456) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 457) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 458) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 459) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 460)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 461) static int mixart_sync_nonblock_events(struct mixart_mgr *mgr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 462) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 463) unsigned long timeout = jiffies + HZ;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 464) while (atomic_read(&mgr->msg_processed) > 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 465) if (time_after(jiffies, timeout)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 466) dev_err(&mgr->pci->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 467) "mixart: cannot process nonblock events!\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 468) return -EBUSY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 469) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 470) schedule_timeout_uninterruptible(1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 471) }
^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) * prepare callback for all pcms
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 477) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 478) static int snd_mixart_prepare(struct snd_pcm_substream *subs)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 479) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 480) struct snd_mixart *chip = snd_pcm_substream_chip(subs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 481) struct mixart_stream *stream = subs->runtime->private_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 482)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 483) /* TODO de façon non bloquante, réappliquer les hw_params (rate, bits, codec) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 484)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 485) dev_dbg(chip->card->dev, "snd_mixart_prepare\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 486)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 487) mixart_sync_nonblock_events(chip->mgr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 488)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 489) /* only the first stream can choose the sample rate */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 490) /* the further opened streams will be limited to its frequency (see open) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 491) if(chip->mgr->ref_count_rate == 1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 492) chip->mgr->sample_rate = subs->runtime->rate;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 493)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 494) /* set the clock only once (first stream) on the same pipe */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 495) if(stream->pipe->references == 1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 496) if( mixart_set_clock(chip->mgr, stream->pipe, subs->runtime->rate) )
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 497) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 498) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 499)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 500) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 501) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 502)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 503)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 504) static int mixart_set_format(struct mixart_stream *stream, snd_pcm_format_t format)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 505) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 506) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 507) struct snd_mixart *chip;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 508) struct mixart_msg request;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 509) struct mixart_stream_param_desc stream_param;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 510) struct mixart_return_uid resp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 511)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 512) chip = snd_pcm_substream_chip(stream->substream);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 513)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 514) memset(&stream_param, 0, sizeof(stream_param));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 515)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 516) stream_param.coding_type = CT_LINEAR;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 517) stream_param.number_of_channel = stream->channels;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 518)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 519) stream_param.sampling_freq = chip->mgr->sample_rate;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 520) if(stream_param.sampling_freq == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 521) stream_param.sampling_freq = 44100; /* if frequency not yet defined, use some default */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 522)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 523) switch(format){
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 524) case SNDRV_PCM_FORMAT_U8:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 525) stream_param.sample_type = ST_INTEGER_8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 526) stream_param.sample_size = 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 527) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 528) case SNDRV_PCM_FORMAT_S16_LE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 529) stream_param.sample_type = ST_INTEGER_16LE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 530) stream_param.sample_size = 16;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 531) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 532) case SNDRV_PCM_FORMAT_S16_BE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 533) stream_param.sample_type = ST_INTEGER_16BE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 534) stream_param.sample_size = 16;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 535) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 536) case SNDRV_PCM_FORMAT_S24_3LE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 537) stream_param.sample_type = ST_INTEGER_24LE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 538) stream_param.sample_size = 24;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 539) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 540) case SNDRV_PCM_FORMAT_S24_3BE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 541) stream_param.sample_type = ST_INTEGER_24BE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 542) stream_param.sample_size = 24;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 543) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 544) case SNDRV_PCM_FORMAT_FLOAT_LE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 545) stream_param.sample_type = ST_FLOATING_POINT_32LE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 546) stream_param.sample_size = 32;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 547) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 548) case SNDRV_PCM_FORMAT_FLOAT_BE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 549) stream_param.sample_type = ST_FLOATING_POINT_32BE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 550) stream_param.sample_size = 32;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 551) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 552) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 553) dev_err(chip->card->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 554) "error mixart_set_format() : unknown format\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 555) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 556) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 557)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 558) dev_dbg(chip->card->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 559) "set SNDRV_PCM_FORMAT sample_type(%d) sample_size(%d) freq(%d) channels(%d)\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 560) stream_param.sample_type, stream_param.sample_size, stream_param.sampling_freq, stream->channels);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 561)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 562) /* TODO: what else to configure ? */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 563) /* stream_param.samples_per_frame = 2; */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 564) /* stream_param.bytes_per_frame = 4; */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 565) /* stream_param.bytes_per_sample = 2; */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 566)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 567) stream_param.pipe_count = 1; /* set to 1 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 568) stream_param.stream_count = 1; /* set to 1 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 569) stream_param.stream_desc[0].uid_pipe = stream->pipe->group_uid;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 570) stream_param.stream_desc[0].stream_idx = stream->substream->number;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 571)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 572) request.message_id = MSG_STREAM_SET_INPUT_STAGE_PARAM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 573) request.uid = (struct mixart_uid){0,0};
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 574) request.data = &stream_param;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 575) request.size = sizeof(stream_param);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 576)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 577) err = snd_mixart_send_msg(chip->mgr, &request, sizeof(resp), &resp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 578) if((err < 0) || resp.error_code) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 579) dev_err(chip->card->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 580) "MSG_STREAM_SET_INPUT_STAGE_PARAM err=%x; resp=%x\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 581) err, resp.error_code);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 582) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 583) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 584) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 585) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 586)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 587)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 588) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 589) * HW_PARAMS callback for all pcms
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 590) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 591) static int snd_mixart_hw_params(struct snd_pcm_substream *subs,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 592) struct snd_pcm_hw_params *hw)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 593) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 594) struct snd_mixart *chip = snd_pcm_substream_chip(subs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 595) struct mixart_mgr *mgr = chip->mgr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 596) struct mixart_stream *stream = subs->runtime->private_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 597) snd_pcm_format_t format;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 598) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 599) int channels;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 600)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 601) /* set up channels */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 602) channels = params_channels(hw);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 603)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 604) /* set up format for the stream */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 605) format = params_format(hw);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 606)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 607) mutex_lock(&mgr->setup_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 608)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 609) /* update the stream levels */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 610) if( stream->pcm_number <= MIXART_PCM_DIGITAL ) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 611) int is_aes = stream->pcm_number > MIXART_PCM_ANALOG;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 612) if( subs->stream == SNDRV_PCM_STREAM_PLAYBACK )
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 613) mixart_update_playback_stream_level(chip, is_aes, subs->number);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 614) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 615) mixart_update_capture_stream_level( chip, is_aes);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 616) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 617)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 618) stream->channels = channels;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 619)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 620) /* set the format to the board */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 621) err = mixart_set_format(stream, format);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 622) if(err < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 623) mutex_unlock(&mgr->setup_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 624) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 625) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 626)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 627) if (subs->runtime->buffer_changed) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 628) struct mixart_bufferinfo *bufferinfo;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 629) int i = (chip->chip_idx * MIXART_MAX_STREAM_PER_CARD) + (stream->pcm_number * (MIXART_PLAYBACK_STREAMS+MIXART_CAPTURE_STREAMS)) + subs->number;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 630) if( subs->stream == SNDRV_PCM_STREAM_CAPTURE ) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 631) i += MIXART_PLAYBACK_STREAMS; /* in array capture is behind playback */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 632) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 633)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 634) bufferinfo = (struct mixart_bufferinfo *)chip->mgr->bufferinfo.area;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 635) bufferinfo[i].buffer_address = subs->runtime->dma_addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 636) bufferinfo[i].available_length = subs->runtime->dma_bytes;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 637) /* bufferinfo[i].buffer_id is already defined */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 638)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 639) dev_dbg(chip->card->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 640) "snd_mixart_hw_params(pcm %d) : dma_addr(%x) dma_bytes(%x) subs-number(%d)\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 641) i, bufferinfo[i].buffer_address,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 642) bufferinfo[i].available_length,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 643) subs->number);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 644) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 645) mutex_unlock(&mgr->setup_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 646)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 647) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 648) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 649)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 650) static int snd_mixart_hw_free(struct snd_pcm_substream *subs)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 651) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 652) struct snd_mixart *chip = snd_pcm_substream_chip(subs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 653) mixart_sync_nonblock_events(chip->mgr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 654) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 655) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 656)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 657)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 658)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 659) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 660) * TODO CONFIGURATION SPACE for all pcms, mono pcm must update channels_max
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 661) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 662) static const struct snd_pcm_hardware snd_mixart_analog_caps =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 663) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 664) .info = ( SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 665) SNDRV_PCM_INFO_MMAP_VALID |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 666) SNDRV_PCM_INFO_PAUSE),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 667) .formats = ( SNDRV_PCM_FMTBIT_U8 |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 668) SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S16_BE |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 669) SNDRV_PCM_FMTBIT_S24_3LE | SNDRV_PCM_FMTBIT_S24_3BE |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 670) SNDRV_PCM_FMTBIT_FLOAT_LE | SNDRV_PCM_FMTBIT_FLOAT_BE ),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 671) .rates = SNDRV_PCM_RATE_CONTINUOUS | SNDRV_PCM_RATE_8000_48000,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 672) .rate_min = 8000,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 673) .rate_max = 48000,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 674) .channels_min = 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 675) .channels_max = 2,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 676) .buffer_bytes_max = (32*1024),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 677) .period_bytes_min = 256, /* 256 frames U8 mono*/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 678) .period_bytes_max = (16*1024),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 679) .periods_min = 2,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 680) .periods_max = (32*1024/256),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 681) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 682)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 683) static const struct snd_pcm_hardware snd_mixart_digital_caps =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 684) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 685) .info = ( SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 686) SNDRV_PCM_INFO_MMAP_VALID |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 687) SNDRV_PCM_INFO_PAUSE),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 688) .formats = ( SNDRV_PCM_FMTBIT_U8 |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 689) SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S16_BE |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 690) SNDRV_PCM_FMTBIT_S24_3LE | SNDRV_PCM_FMTBIT_S24_3BE |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 691) SNDRV_PCM_FMTBIT_FLOAT_LE | SNDRV_PCM_FMTBIT_FLOAT_BE ),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 692) .rates = SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 693) .rate_min = 32000,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 694) .rate_max = 48000,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 695) .channels_min = 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 696) .channels_max = 2,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 697) .buffer_bytes_max = (32*1024),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 698) .period_bytes_min = 256, /* 256 frames U8 mono*/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 699) .period_bytes_max = (16*1024),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 700) .periods_min = 2,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 701) .periods_max = (32*1024/256),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 702) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 703)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 704)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 705) static int snd_mixart_playback_open(struct snd_pcm_substream *subs)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 706) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 707) struct snd_mixart *chip = snd_pcm_substream_chip(subs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 708) struct mixart_mgr *mgr = chip->mgr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 709) struct snd_pcm_runtime *runtime = subs->runtime;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 710) struct snd_pcm *pcm = subs->pcm;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 711) struct mixart_stream *stream;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 712) struct mixart_pipe *pipe;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 713) int err = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 714) int pcm_number;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 715)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 716) mutex_lock(&mgr->setup_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 717)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 718) if ( pcm == chip->pcm ) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 719) pcm_number = MIXART_PCM_ANALOG;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 720) runtime->hw = snd_mixart_analog_caps;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 721) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 722) snd_BUG_ON(pcm != chip->pcm_dig);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 723) pcm_number = MIXART_PCM_DIGITAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 724) runtime->hw = snd_mixart_digital_caps;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 725) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 726) dev_dbg(chip->card->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 727) "snd_mixart_playback_open C%d/P%d/Sub%d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 728) chip->chip_idx, pcm_number, subs->number);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 729)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 730) /* get stream info */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 731) stream = &(chip->playback_stream[pcm_number][subs->number]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 732)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 733) if (stream->status != MIXART_STREAM_STATUS_FREE){
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 734) /* streams in use */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 735) dev_err(chip->card->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 736) "snd_mixart_playback_open C%d/P%d/Sub%d in use\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 737) chip->chip_idx, pcm_number, subs->number);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 738) err = -EBUSY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 739) goto _exit_open;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 740) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 741)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 742) /* get pipe pointer (out pipe) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 743) pipe = snd_mixart_add_ref_pipe(chip, pcm_number, 0, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 744)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 745) if (pipe == NULL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 746) err = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 747) goto _exit_open;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 748) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 749)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 750) /* start the pipe if necessary */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 751) err = mixart_set_pipe_state(chip->mgr, pipe, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 752) if( err < 0 ) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 753) dev_err(chip->card->dev, "error starting pipe!\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 754) snd_mixart_kill_ref_pipe(chip->mgr, pipe, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 755) err = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 756) goto _exit_open;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 757) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 758)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 759) stream->pipe = pipe;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 760) stream->pcm_number = pcm_number;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 761) stream->status = MIXART_STREAM_STATUS_OPEN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 762) stream->substream = subs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 763) stream->channels = 0; /* not configured yet */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 764)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 765) runtime->private_data = stream;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 766)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 767) snd_pcm_hw_constraint_step(runtime, 0, SNDRV_PCM_HW_PARAM_PERIOD_BYTES, 32);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 768) snd_pcm_hw_constraint_step(runtime, 0, SNDRV_PCM_HW_PARAM_BUFFER_SIZE, 64);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 769)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 770) /* if a sample rate is already used, another stream cannot change */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 771) if(mgr->ref_count_rate++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 772) if(mgr->sample_rate) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 773) runtime->hw.rate_min = runtime->hw.rate_max = mgr->sample_rate;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 774) }
^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) _exit_open:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 778) mutex_unlock(&mgr->setup_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 779)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 780) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 781) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 782)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 783)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 784) static int snd_mixart_capture_open(struct snd_pcm_substream *subs)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 785) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 786) struct snd_mixart *chip = snd_pcm_substream_chip(subs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 787) struct mixart_mgr *mgr = chip->mgr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 788) struct snd_pcm_runtime *runtime = subs->runtime;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 789) struct snd_pcm *pcm = subs->pcm;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 790) struct mixart_stream *stream;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 791) struct mixart_pipe *pipe;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 792) int err = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 793) int pcm_number;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 794)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 795) mutex_lock(&mgr->setup_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 796)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 797) if ( pcm == chip->pcm ) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 798) pcm_number = MIXART_PCM_ANALOG;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 799) runtime->hw = snd_mixart_analog_caps;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 800) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 801) snd_BUG_ON(pcm != chip->pcm_dig);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 802) pcm_number = MIXART_PCM_DIGITAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 803) runtime->hw = snd_mixart_digital_caps;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 804) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 805)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 806) runtime->hw.channels_min = 2; /* for instance, no mono */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 807)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 808) dev_dbg(chip->card->dev, "snd_mixart_capture_open C%d/P%d/Sub%d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 809) chip->chip_idx, pcm_number, subs->number);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 810)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 811) /* get stream info */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 812) stream = &(chip->capture_stream[pcm_number]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 813)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 814) if (stream->status != MIXART_STREAM_STATUS_FREE){
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 815) /* streams in use */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 816) dev_err(chip->card->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 817) "snd_mixart_capture_open C%d/P%d/Sub%d in use\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 818) chip->chip_idx, pcm_number, subs->number);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 819) err = -EBUSY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 820) goto _exit_open;
^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) /* get pipe pointer (in pipe) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 824) pipe = snd_mixart_add_ref_pipe(chip, pcm_number, 1, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 825)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 826) if (pipe == NULL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 827) err = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 828) goto _exit_open;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 829) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 830)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 831) /* start the pipe if necessary */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 832) err = mixart_set_pipe_state(chip->mgr, pipe, 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 833) if( err < 0 ) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 834) dev_err(chip->card->dev, "error starting pipe!\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 835) snd_mixart_kill_ref_pipe(chip->mgr, pipe, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 836) err = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 837) goto _exit_open;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 838) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 839)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 840) stream->pipe = pipe;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 841) stream->pcm_number = pcm_number;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 842) stream->status = MIXART_STREAM_STATUS_OPEN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 843) stream->substream = subs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 844) stream->channels = 0; /* not configured yet */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 845)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 846) runtime->private_data = stream;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 847)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 848) snd_pcm_hw_constraint_step(runtime, 0, SNDRV_PCM_HW_PARAM_PERIOD_BYTES, 32);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 849) snd_pcm_hw_constraint_step(runtime, 0, SNDRV_PCM_HW_PARAM_BUFFER_SIZE, 64);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 850)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 851) /* if a sample rate is already used, another stream cannot change */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 852) if(mgr->ref_count_rate++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 853) if(mgr->sample_rate) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 854) runtime->hw.rate_min = runtime->hw.rate_max = mgr->sample_rate;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 855) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 856) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 857)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 858) _exit_open:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 859) mutex_unlock(&mgr->setup_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 860)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 861) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 862) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 863)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 864)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 865)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 866) static int snd_mixart_close(struct snd_pcm_substream *subs)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 867) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 868) struct snd_mixart *chip = snd_pcm_substream_chip(subs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 869) struct mixart_mgr *mgr = chip->mgr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 870) struct mixart_stream *stream = subs->runtime->private_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 871)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 872) mutex_lock(&mgr->setup_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 873)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 874) dev_dbg(chip->card->dev, "snd_mixart_close C%d/P%d/Sub%d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 875) chip->chip_idx, stream->pcm_number, subs->number);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 876)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 877) /* sample rate released */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 878) if(--mgr->ref_count_rate == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 879) mgr->sample_rate = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 880) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 881)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 882) /* delete pipe */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 883) if (snd_mixart_kill_ref_pipe(mgr, stream->pipe, 0 ) < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 884)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 885) dev_err(chip->card->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 886) "error snd_mixart_kill_ref_pipe C%dP%d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 887) chip->chip_idx, stream->pcm_number);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 888) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 889)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 890) stream->pipe = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 891) stream->status = MIXART_STREAM_STATUS_FREE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 892) stream->substream = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 893)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 894) mutex_unlock(&mgr->setup_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 895) return 0;
^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) static snd_pcm_uframes_t snd_mixart_stream_pointer(struct snd_pcm_substream *subs)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 900) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 901) struct snd_pcm_runtime *runtime = subs->runtime;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 902) struct mixart_stream *stream = runtime->private_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 903)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 904) return (snd_pcm_uframes_t)((stream->buf_periods * runtime->period_size) + stream->buf_period_frag);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 905) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 906)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 907)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 908)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 909) static const struct snd_pcm_ops snd_mixart_playback_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 910) .open = snd_mixart_playback_open,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 911) .close = snd_mixart_close,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 912) .prepare = snd_mixart_prepare,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 913) .hw_params = snd_mixart_hw_params,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 914) .hw_free = snd_mixart_hw_free,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 915) .trigger = snd_mixart_trigger,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 916) .pointer = snd_mixart_stream_pointer,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 917) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 918)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 919) static const struct snd_pcm_ops snd_mixart_capture_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 920) .open = snd_mixart_capture_open,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 921) .close = snd_mixart_close,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 922) .prepare = snd_mixart_prepare,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 923) .hw_params = snd_mixart_hw_params,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 924) .hw_free = snd_mixart_hw_free,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 925) .trigger = snd_mixart_trigger,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 926) .pointer = snd_mixart_stream_pointer,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 927) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 928)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 929) static void preallocate_buffers(struct snd_mixart *chip, struct snd_pcm *pcm)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 930) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 931) #if 0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 932) struct snd_pcm_substream *subs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 933) int stream;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 934)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 935) for (stream = 0; stream < 2; stream++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 936) int idx = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 937) for (subs = pcm->streams[stream].substream; subs; subs = subs->next, idx++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 938) /* set up the unique device id with the chip index */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 939) subs->dma_device.id = subs->pcm->device << 16 |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 940) subs->stream << 8 | (subs->number + 1) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 941) (chip->chip_idx + 1) << 24;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 942) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 943) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 944) snd_pcm_set_managed_buffer_all(pcm, SNDRV_DMA_TYPE_DEV,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 945) &chip->mgr->pci->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 946) 32*1024, 32*1024);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 947) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 948)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 949) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 950) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 951) static int snd_mixart_pcm_analog(struct snd_mixart *chip)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 952) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 953) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 954) struct snd_pcm *pcm;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 955) char name[32];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 956)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 957) sprintf(name, "miXart analog %d", chip->chip_idx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 958) if ((err = snd_pcm_new(chip->card, name, MIXART_PCM_ANALOG,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 959) MIXART_PLAYBACK_STREAMS,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 960) MIXART_CAPTURE_STREAMS, &pcm)) < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 961) dev_err(chip->card->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 962) "cannot create the analog pcm %d\n", chip->chip_idx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 963) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 964) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 965)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 966) pcm->private_data = chip;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 967)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 968) snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &snd_mixart_playback_ops);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 969) snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &snd_mixart_capture_ops);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 970)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 971) pcm->info_flags = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 972) pcm->nonatomic = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 973) strcpy(pcm->name, name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 974)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 975) preallocate_buffers(chip, pcm);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 976)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 977) chip->pcm = pcm;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 978) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 979) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 980)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 981)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 982) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 983) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 984) static int snd_mixart_pcm_digital(struct snd_mixart *chip)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 985) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 986) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 987) struct snd_pcm *pcm;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 988) char name[32];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 989)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 990) sprintf(name, "miXart AES/EBU %d", chip->chip_idx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 991) if ((err = snd_pcm_new(chip->card, name, MIXART_PCM_DIGITAL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 992) MIXART_PLAYBACK_STREAMS,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 993) MIXART_CAPTURE_STREAMS, &pcm)) < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 994) dev_err(chip->card->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 995) "cannot create the digital pcm %d\n", chip->chip_idx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 996) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 997) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 998)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 999) pcm->private_data = chip;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1000)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1001) snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &snd_mixart_playback_ops);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1002) snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &snd_mixart_capture_ops);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1003)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1004) pcm->info_flags = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1005) pcm->nonatomic = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1006) strcpy(pcm->name, name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1007)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1008) preallocate_buffers(chip, pcm);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1009)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1010) chip->pcm_dig = pcm;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1011) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1012) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1013)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1014) static int snd_mixart_chip_free(struct snd_mixart *chip)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1015) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1016) kfree(chip);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1017) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1018) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1019)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1020) static int snd_mixart_chip_dev_free(struct snd_device *device)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1021) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1022) struct snd_mixart *chip = device->device_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1023) return snd_mixart_chip_free(chip);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1024) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1025)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1026)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1027) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1028) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1029) static int snd_mixart_create(struct mixart_mgr *mgr, struct snd_card *card, int idx)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1030) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1031) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1032) struct snd_mixart *chip;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1033) static const struct snd_device_ops ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1034) .dev_free = snd_mixart_chip_dev_free,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1035) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1036)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1037) chip = kzalloc(sizeof(*chip), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1038) if (!chip)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1039) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1040)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1041) chip->card = card;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1042) chip->chip_idx = idx;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1043) chip->mgr = mgr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1044) card->sync_irq = mgr->irq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1045)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1046) if ((err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, chip, &ops)) < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1047) snd_mixart_chip_free(chip);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1048) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1049) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1050)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1051) mgr->chip[idx] = chip;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1052) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1053) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1054)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1055) int snd_mixart_create_pcm(struct snd_mixart* chip)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1056) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1057) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1058)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1059) err = snd_mixart_pcm_analog(chip);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1060) if (err < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1061) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1062)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1063) if(chip->mgr->board_type == MIXART_DAUGHTER_TYPE_AES) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1064)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1065) err = snd_mixart_pcm_digital(chip);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1066) if (err < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1067) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1068) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1069) return err;
^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) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1074) * release all the cards assigned to a manager instance
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1075) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1076) static int snd_mixart_free(struct mixart_mgr *mgr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1077) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1078) unsigned int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1079)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1080) for (i = 0; i < mgr->num_cards; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1081) if (mgr->chip[i])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1082) snd_card_free(mgr->chip[i]->card);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1083) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1084)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1085) /* stop mailbox */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1086) snd_mixart_exit_mailbox(mgr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1087)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1088) /* release irq */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1089) if (mgr->irq >= 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1090) free_irq(mgr->irq, mgr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1091)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1092) /* reset board if some firmware was loaded */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1093) if(mgr->dsp_loaded) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1094) snd_mixart_reset_board(mgr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1095) dev_dbg(&mgr->pci->dev, "reset miXart !\n");
^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) /* release the i/o ports */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1099) for (i = 0; i < 2; ++i)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1100) iounmap(mgr->mem[i].virt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1101)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1102) pci_release_regions(mgr->pci);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1103)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1104) /* free flowarray */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1105) if(mgr->flowinfo.area) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1106) snd_dma_free_pages(&mgr->flowinfo);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1107) mgr->flowinfo.area = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1108) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1109) /* free bufferarray */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1110) if(mgr->bufferinfo.area) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1111) snd_dma_free_pages(&mgr->bufferinfo);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1112) mgr->bufferinfo.area = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1113) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1114)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1115) pci_disable_device(mgr->pci);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1116) kfree(mgr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1117) return 0;
^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) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1121) * proc interface
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1122) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1123)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1124) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1125) mixart_BA0 proc interface for BAR 0 - read callback
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1126) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1127) static ssize_t snd_mixart_BA0_read(struct snd_info_entry *entry,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1128) void *file_private_data,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1129) struct file *file, char __user *buf,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1130) size_t count, loff_t pos)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1131) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1132) struct mixart_mgr *mgr = entry->private_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1133)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1134) count = count & ~3; /* make sure the read size is a multiple of 4 bytes */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1135) if (copy_to_user_fromio(buf, MIXART_MEM(mgr, pos), count))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1136) return -EFAULT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1137) return count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1138) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1139)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1140) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1141) mixart_BA1 proc interface for BAR 1 - read callback
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1142) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1143) static ssize_t snd_mixart_BA1_read(struct snd_info_entry *entry,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1144) void *file_private_data,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1145) struct file *file, char __user *buf,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1146) size_t count, loff_t pos)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1147) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1148) struct mixart_mgr *mgr = entry->private_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1149)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1150) count = count & ~3; /* make sure the read size is a multiple of 4 bytes */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1151) if (copy_to_user_fromio(buf, MIXART_REG(mgr, pos), count))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1152) return -EFAULT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1153) return count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1154) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1155)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1156) static const struct snd_info_entry_ops snd_mixart_proc_ops_BA0 = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1157) .read = snd_mixart_BA0_read,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1158) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1159)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1160) static const struct snd_info_entry_ops snd_mixart_proc_ops_BA1 = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1161) .read = snd_mixart_BA1_read,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1162) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1163)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1164)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1165) static void snd_mixart_proc_read(struct snd_info_entry *entry,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1166) struct snd_info_buffer *buffer)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1167) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1168) struct snd_mixart *chip = entry->private_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1169) u32 ref;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1170)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1171) snd_iprintf(buffer, "Digigram miXart (alsa card %d)\n\n", chip->chip_idx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1172)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1173) /* stats available when embedded OS is running */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1174) if (chip->mgr->dsp_loaded & ( 1 << MIXART_MOTHERBOARD_ELF_INDEX)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1175) snd_iprintf(buffer, "- hardware -\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1176) switch (chip->mgr->board_type ) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1177) case MIXART_DAUGHTER_TYPE_NONE : snd_iprintf(buffer, "\tmiXart8 (no daughter board)\n\n"); break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1178) case MIXART_DAUGHTER_TYPE_AES : snd_iprintf(buffer, "\tmiXart8 AES/EBU\n\n"); break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1179) case MIXART_DAUGHTER_TYPE_COBRANET : snd_iprintf(buffer, "\tmiXart8 Cobranet\n\n"); break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1180) default: snd_iprintf(buffer, "\tUNKNOWN!\n\n"); break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1181) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1182)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1183) snd_iprintf(buffer, "- system load -\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1184)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1185) /* get perf reference */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1186)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1187) ref = readl_be( MIXART_MEM( chip->mgr, MIXART_PSEUDOREG_PERF_SYSTEM_LOAD_OFFSET));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1188)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1189) if (ref) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1190) u32 mailbox = 100 * readl_be( MIXART_MEM( chip->mgr, MIXART_PSEUDOREG_PERF_MAILBX_LOAD_OFFSET)) / ref;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1191) u32 streaming = 100 * readl_be( MIXART_MEM( chip->mgr, MIXART_PSEUDOREG_PERF_STREAM_LOAD_OFFSET)) / ref;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1192) u32 interr = 100 * readl_be( MIXART_MEM( chip->mgr, MIXART_PSEUDOREG_PERF_INTERR_LOAD_OFFSET)) / ref;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1193)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1194) snd_iprintf(buffer, "\tstreaming : %d\n", streaming);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1195) snd_iprintf(buffer, "\tmailbox : %d\n", mailbox);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1196) snd_iprintf(buffer, "\tinterrupts handling : %d\n\n", interr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1197) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1198) } /* endif elf loaded */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1199) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1200)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1201) static void snd_mixart_proc_init(struct snd_mixart *chip)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1202) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1203) struct snd_info_entry *entry;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1204)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1205) /* text interface to read perf and temp meters */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1206) snd_card_ro_proc_new(chip->card, "board_info", chip,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1207) snd_mixart_proc_read);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1208)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1209) if (! snd_card_proc_new(chip->card, "mixart_BA0", &entry)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1210) entry->content = SNDRV_INFO_CONTENT_DATA;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1211) entry->private_data = chip->mgr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1212) entry->c.ops = &snd_mixart_proc_ops_BA0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1213) entry->size = MIXART_BA0_SIZE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1214) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1215) if (! snd_card_proc_new(chip->card, "mixart_BA1", &entry)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1216) entry->content = SNDRV_INFO_CONTENT_DATA;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1217) entry->private_data = chip->mgr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1218) entry->c.ops = &snd_mixart_proc_ops_BA1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1219) entry->size = MIXART_BA1_SIZE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1220) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1221) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1222) /* end of proc interface */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1223)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1224)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1225) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1226) * probe function - creates the card manager
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1227) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1228) static int snd_mixart_probe(struct pci_dev *pci,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1229) const struct pci_device_id *pci_id)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1230) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1231) static int dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1232) struct mixart_mgr *mgr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1233) unsigned int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1234) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1235) size_t size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1236)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1237) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1238) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1239) if (dev >= SNDRV_CARDS)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1240) return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1241) if (! enable[dev]) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1242) dev++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1243) return -ENOENT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1244) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1245)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1246) /* enable PCI device */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1247) if ((err = pci_enable_device(pci)) < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1248) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1249) pci_set_master(pci);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1250)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1251) /* check if we can restrict PCI DMA transfers to 32 bits */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1252) if (dma_set_mask(&pci->dev, DMA_BIT_MASK(32)) < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1253) dev_err(&pci->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1254) "architecture does not support 32bit PCI busmaster DMA\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1255) pci_disable_device(pci);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1256) return -ENXIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1257) }
^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) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1261) mgr = kzalloc(sizeof(*mgr), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1262) if (! mgr) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1263) pci_disable_device(pci);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1264) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1265) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1266)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1267) mgr->pci = pci;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1268) mgr->irq = -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1269)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1270) /* resource assignment */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1271) if ((err = pci_request_regions(pci, CARD_NAME)) < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1272) kfree(mgr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1273) pci_disable_device(pci);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1274) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1275) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1276) for (i = 0; i < 2; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1277) mgr->mem[i].phys = pci_resource_start(pci, i);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1278) mgr->mem[i].virt = pci_ioremap_bar(pci, i);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1279) if (!mgr->mem[i].virt) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1280) dev_err(&pci->dev, "unable to remap resource 0x%lx\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1281) mgr->mem[i].phys);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1282) snd_mixart_free(mgr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1283) return -EBUSY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1284) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1285) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1286)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1287) if (request_threaded_irq(pci->irq, snd_mixart_interrupt,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1288) snd_mixart_threaded_irq, IRQF_SHARED,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1289) KBUILD_MODNAME, mgr)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1290) dev_err(&pci->dev, "unable to grab IRQ %d\n", pci->irq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1291) snd_mixart_free(mgr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1292) return -EBUSY;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1293) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1294) mgr->irq = pci->irq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1295)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1296) /* init mailbox */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1297) mgr->msg_fifo_readptr = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1298) mgr->msg_fifo_writeptr = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1299)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1300) mutex_init(&mgr->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1301) mutex_init(&mgr->msg_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1302) init_waitqueue_head(&mgr->msg_sleep);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1303) atomic_set(&mgr->msg_processed, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1304)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1305) /* init setup mutex*/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1306) mutex_init(&mgr->setup_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1307)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1308) /* card assignment */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1309) mgr->num_cards = MIXART_MAX_CARDS; /* 4 FIXME: configurable? */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1310) for (i = 0; i < mgr->num_cards; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1311) struct snd_card *card;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1312) char tmpid[16];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1313) int idx;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1314)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1315) if (index[dev] < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1316) idx = index[dev];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1317) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1318) idx = index[dev] + i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1319) snprintf(tmpid, sizeof(tmpid), "%s-%d", id[dev] ? id[dev] : "MIXART", i);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1320) err = snd_card_new(&pci->dev, idx, tmpid, THIS_MODULE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1321) 0, &card);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1322)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1323) if (err < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1324) dev_err(&pci->dev, "cannot allocate the card %d\n", i);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1325) snd_mixart_free(mgr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1326) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1327) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1328)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1329) strcpy(card->driver, CARD_NAME);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1330) snprintf(card->shortname, sizeof(card->shortname),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1331) "Digigram miXart [PCM #%d]", i);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1332) snprintf(card->longname, sizeof(card->longname),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1333) "Digigram miXart at 0x%lx & 0x%lx, irq %i [PCM #%d]",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1334) mgr->mem[0].phys, mgr->mem[1].phys, mgr->irq, i);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1335)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1336) if ((err = snd_mixart_create(mgr, card, i)) < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1337) snd_card_free(card);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1338) snd_mixart_free(mgr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1339) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1340) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1341)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1342) if(i==0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1343) /* init proc interface only for chip0 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1344) snd_mixart_proc_init(mgr->chip[i]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1345) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1346)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1347) if ((err = snd_card_register(card)) < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1348) snd_mixart_free(mgr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1349) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1350) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1351) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1352)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1353) /* init firmware status (mgr->dsp_loaded reset in hwdep_new) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1354) mgr->board_type = MIXART_DAUGHTER_TYPE_NONE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1355)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1356) /* create array of streaminfo */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1357) size = PAGE_ALIGN( (MIXART_MAX_STREAM_PER_CARD * MIXART_MAX_CARDS *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1358) sizeof(struct mixart_flowinfo)) );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1359) if (snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, &pci->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1360) size, &mgr->flowinfo) < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1361) snd_mixart_free(mgr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1362) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1363) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1364) /* init streaminfo_array */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1365) memset(mgr->flowinfo.area, 0, size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1366)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1367) /* create array of bufferinfo */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1368) size = PAGE_ALIGN( (MIXART_MAX_STREAM_PER_CARD * MIXART_MAX_CARDS *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1369) sizeof(struct mixart_bufferinfo)) );
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1370) if (snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, &pci->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1371) size, &mgr->bufferinfo) < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1372) snd_mixart_free(mgr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1373) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1374) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1375) /* init bufferinfo_array */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1376) memset(mgr->bufferinfo.area, 0, size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1377)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1378) /* set up firmware */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1379) err = snd_mixart_setup_firmware(mgr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1380) if (err < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1381) snd_mixart_free(mgr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1382) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1383) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1384)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1385) pci_set_drvdata(pci, mgr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1386) dev++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1387) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1388) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1389)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1390) static void snd_mixart_remove(struct pci_dev *pci)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1391) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1392) snd_mixart_free(pci_get_drvdata(pci));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1393) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1394)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1395) static struct pci_driver mixart_driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1396) .name = KBUILD_MODNAME,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1397) .id_table = snd_mixart_ids,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1398) .probe = snd_mixart_probe,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1399) .remove = snd_mixart_remove,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1400) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1401)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1402) module_pci_driver(mixart_driver);