^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * McBSP Sidetone support
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) * Copyright (C) 2004 Nokia Corporation
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) * Author: Samuel Ortiz <samuel.ortiz@nokia.com>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) * Contact: Jarkko Nikula <jarkko.nikula@bitmer.com>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) * Peter Ujfalusi <peter.ujfalusi@ti.com>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) #include <linux/module.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) #include <linux/init.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) #include <linux/device.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) #include <linux/platform_device.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) #include <linux/interrupt.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) #include <linux/err.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) #include <linux/clk.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) #include <linux/delay.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) #include <linux/io.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) #include <linux/slab.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) #include <linux/pm_runtime.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) #include "omap-mcbsp.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) #include "omap-mcbsp-priv.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) /* OMAP3 sidetone control registers */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) #define OMAP_ST_REG_REV 0x00
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) #define OMAP_ST_REG_SYSCONFIG 0x10
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) #define OMAP_ST_REG_IRQSTATUS 0x18
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) #define OMAP_ST_REG_IRQENABLE 0x1C
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) #define OMAP_ST_REG_SGAINCR 0x24
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) #define OMAP_ST_REG_SFIRCR 0x28
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) #define OMAP_ST_REG_SSELCR 0x2C
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) /********************** McBSP SSELCR bit definitions ***********************/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) #define SIDETONEEN BIT(10)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) /********************** McBSP Sidetone SYSCONFIG bit definitions ***********/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) #define ST_AUTOIDLE BIT(0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) /********************** McBSP Sidetone SGAINCR bit definitions *************/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) #define ST_CH0GAIN(value) ((value) & 0xffff) /* Bits 0:15 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) #define ST_CH1GAIN(value) (((value) & 0xffff) << 16) /* Bits 16:31 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) /********************** McBSP Sidetone SFIRCR bit definitions **************/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) #define ST_FIRCOEFF(value) ((value) & 0xffff) /* Bits 0:15 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) /********************** McBSP Sidetone SSELCR bit definitions **************/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) #define ST_SIDETONEEN BIT(0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) #define ST_COEFFWREN BIT(1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) #define ST_COEFFWRDONE BIT(2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) struct omap_mcbsp_st_data {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) void __iomem *io_base_st;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) struct clk *mcbsp_iclk;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) bool running;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) bool enabled;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) s16 taps[128]; /* Sidetone filter coefficients */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) int nr_taps; /* Number of filter coefficients in use */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) s16 ch0gain;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) s16 ch1gain;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) static void omap_mcbsp_st_write(struct omap_mcbsp *mcbsp, u16 reg, u32 val)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) writel_relaxed(val, mcbsp->st_data->io_base_st + reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) static int omap_mcbsp_st_read(struct omap_mcbsp *mcbsp, u16 reg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) return readl_relaxed(mcbsp->st_data->io_base_st + reg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) #define MCBSP_ST_READ(mcbsp, reg) omap_mcbsp_st_read(mcbsp, OMAP_ST_REG_##reg)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) #define MCBSP_ST_WRITE(mcbsp, reg, val) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) omap_mcbsp_st_write(mcbsp, OMAP_ST_REG_##reg, val)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) static void omap_mcbsp_st_on(struct omap_mcbsp *mcbsp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) unsigned int w;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) if (mcbsp->pdata->force_ick_on)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) mcbsp->pdata->force_ick_on(mcbsp->st_data->mcbsp_iclk, true);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) /* Disable Sidetone clock auto-gating for normal operation */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) w = MCBSP_ST_READ(mcbsp, SYSCONFIG);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) MCBSP_ST_WRITE(mcbsp, SYSCONFIG, w & ~(ST_AUTOIDLE));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) /* Enable McBSP Sidetone */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) w = MCBSP_READ(mcbsp, SSELCR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) MCBSP_WRITE(mcbsp, SSELCR, w | SIDETONEEN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) /* Enable Sidetone from Sidetone Core */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) w = MCBSP_ST_READ(mcbsp, SSELCR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) MCBSP_ST_WRITE(mcbsp, SSELCR, w | ST_SIDETONEEN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) static void omap_mcbsp_st_off(struct omap_mcbsp *mcbsp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) unsigned int w;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) w = MCBSP_ST_READ(mcbsp, SSELCR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) MCBSP_ST_WRITE(mcbsp, SSELCR, w & ~(ST_SIDETONEEN));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) w = MCBSP_READ(mcbsp, SSELCR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) MCBSP_WRITE(mcbsp, SSELCR, w & ~(SIDETONEEN));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) /* Enable Sidetone clock auto-gating to reduce power consumption */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) w = MCBSP_ST_READ(mcbsp, SYSCONFIG);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) MCBSP_ST_WRITE(mcbsp, SYSCONFIG, w | ST_AUTOIDLE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) if (mcbsp->pdata->force_ick_on)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) mcbsp->pdata->force_ick_on(mcbsp->st_data->mcbsp_iclk, false);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) static void omap_mcbsp_st_fir_write(struct omap_mcbsp *mcbsp, s16 *fir)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) u16 val, i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) val = MCBSP_ST_READ(mcbsp, SSELCR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) if (val & ST_COEFFWREN)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) MCBSP_ST_WRITE(mcbsp, SSELCR, val & ~(ST_COEFFWREN));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) MCBSP_ST_WRITE(mcbsp, SSELCR, val | ST_COEFFWREN);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) for (i = 0; i < 128; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) MCBSP_ST_WRITE(mcbsp, SFIRCR, fir[i]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) i = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) val = MCBSP_ST_READ(mcbsp, SSELCR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) while (!(val & ST_COEFFWRDONE) && (++i < 1000))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) val = MCBSP_ST_READ(mcbsp, SSELCR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) MCBSP_ST_WRITE(mcbsp, SSELCR, val & ~(ST_COEFFWREN));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) if (i == 1000)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) dev_err(mcbsp->dev, "McBSP FIR load error!\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) static void omap_mcbsp_st_chgain(struct omap_mcbsp *mcbsp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) struct omap_mcbsp_st_data *st_data = mcbsp->st_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) MCBSP_ST_WRITE(mcbsp, SGAINCR, ST_CH0GAIN(st_data->ch0gain) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) ST_CH1GAIN(st_data->ch1gain));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) static int omap_mcbsp_st_set_chgain(struct omap_mcbsp *mcbsp, int channel,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) s16 chgain)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) struct omap_mcbsp_st_data *st_data = mcbsp->st_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) int ret = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) if (!st_data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) return -ENOENT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) spin_lock_irq(&mcbsp->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) if (channel == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) st_data->ch0gain = chgain;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) else if (channel == 1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) st_data->ch1gain = chgain;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) ret = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) if (st_data->enabled)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) omap_mcbsp_st_chgain(mcbsp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) spin_unlock_irq(&mcbsp->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) static int omap_mcbsp_st_get_chgain(struct omap_mcbsp *mcbsp, int channel,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) s16 *chgain)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) struct omap_mcbsp_st_data *st_data = mcbsp->st_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) int ret = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) if (!st_data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) return -ENOENT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) spin_lock_irq(&mcbsp->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) if (channel == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) *chgain = st_data->ch0gain;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) else if (channel == 1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) *chgain = st_data->ch1gain;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) ret = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) spin_unlock_irq(&mcbsp->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) static int omap_mcbsp_st_enable(struct omap_mcbsp *mcbsp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) struct omap_mcbsp_st_data *st_data = mcbsp->st_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) if (!st_data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) spin_lock_irq(&mcbsp->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) st_data->enabled = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) omap_mcbsp_st_start(mcbsp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) spin_unlock_irq(&mcbsp->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) static int omap_mcbsp_st_disable(struct omap_mcbsp *mcbsp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) struct omap_mcbsp_st_data *st_data = mcbsp->st_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) int ret = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) if (!st_data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) spin_lock_irq(&mcbsp->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) omap_mcbsp_st_stop(mcbsp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) st_data->enabled = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) spin_unlock_irq(&mcbsp->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) static int omap_mcbsp_st_is_enabled(struct omap_mcbsp *mcbsp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) struct omap_mcbsp_st_data *st_data = mcbsp->st_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) if (!st_data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) return -ENODEV;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) return st_data->enabled;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) static ssize_t st_taps_show(struct device *dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) struct device_attribute *attr, char *buf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) struct omap_mcbsp *mcbsp = dev_get_drvdata(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) struct omap_mcbsp_st_data *st_data = mcbsp->st_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) ssize_t status = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) spin_lock_irq(&mcbsp->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) for (i = 0; i < st_data->nr_taps; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) status += sprintf(&buf[status], (i ? ", %d" : "%d"),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) st_data->taps[i]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) if (i)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) status += sprintf(&buf[status], "\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) spin_unlock_irq(&mcbsp->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) return status;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) static ssize_t st_taps_store(struct device *dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) struct device_attribute *attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) const char *buf, size_t size)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) struct omap_mcbsp *mcbsp = dev_get_drvdata(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) struct omap_mcbsp_st_data *st_data = mcbsp->st_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) int val, tmp, status, i = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) spin_lock_irq(&mcbsp->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) memset(st_data->taps, 0, sizeof(st_data->taps));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) st_data->nr_taps = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) do {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) status = sscanf(buf, "%d%n", &val, &tmp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) if (status < 0 || status == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) size = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) if (val < -32768 || val > 32767) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) size = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) st_data->taps[i++] = val;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) buf += tmp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) if (*buf != ',')
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) buf++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) } while (1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) st_data->nr_taps = i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) spin_unlock_irq(&mcbsp->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) return size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) static DEVICE_ATTR_RW(st_taps);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) static const struct attribute *sidetone_attrs[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) &dev_attr_st_taps.attr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) NULL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) static const struct attribute_group sidetone_attr_group = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) .attrs = (struct attribute **)sidetone_attrs,
^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) int omap_mcbsp_st_start(struct omap_mcbsp *mcbsp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) struct omap_mcbsp_st_data *st_data = mcbsp->st_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) if (st_data->enabled && !st_data->running) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) omap_mcbsp_st_fir_write(mcbsp, st_data->taps);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) omap_mcbsp_st_chgain(mcbsp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) if (!mcbsp->free) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) omap_mcbsp_st_on(mcbsp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) st_data->running = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) int omap_mcbsp_st_stop(struct omap_mcbsp *mcbsp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) struct omap_mcbsp_st_data *st_data = mcbsp->st_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) if (st_data->running) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) if (!mcbsp->free) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) omap_mcbsp_st_off(mcbsp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) st_data->running = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) int omap_mcbsp_st_init(struct platform_device *pdev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) struct omap_mcbsp *mcbsp = platform_get_drvdata(pdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) struct omap_mcbsp_st_data *st_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339) struct resource *res;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "sidetone");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) if (!res)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) st_data = devm_kzalloc(mcbsp->dev, sizeof(*mcbsp->st_data), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347) if (!st_data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350) st_data->mcbsp_iclk = clk_get(mcbsp->dev, "ick");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351) if (IS_ERR(st_data->mcbsp_iclk)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352) dev_warn(mcbsp->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353) "Failed to get ick, sidetone might be broken\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354) st_data->mcbsp_iclk = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357) st_data->io_base_st = devm_ioremap(mcbsp->dev, res->start,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358) resource_size(res));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359) if (!st_data->io_base_st)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362) ret = sysfs_create_group(&mcbsp->dev->kobj, &sidetone_attr_group);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366) mcbsp->st_data = st_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371) void omap_mcbsp_st_cleanup(struct platform_device *pdev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373) struct omap_mcbsp *mcbsp = platform_get_drvdata(pdev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375) if (mcbsp->st_data) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376) sysfs_remove_group(&mcbsp->dev->kobj, &sidetone_attr_group);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377) clk_put(mcbsp->st_data->mcbsp_iclk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378) }
^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 omap_mcbsp_st_info_volsw(struct snd_kcontrol *kcontrol,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382) struct snd_ctl_elem_info *uinfo)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384) struct soc_mixer_control *mc =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385) (struct soc_mixer_control *)kcontrol->private_value;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386) int max = mc->max;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387) int min = mc->min;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389) uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390) uinfo->count = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391) uinfo->value.integer.min = min;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392) uinfo->value.integer.max = max;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396) #define OMAP_MCBSP_ST_CHANNEL_VOLUME(channel) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397) static int \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398) omap_mcbsp_set_st_ch##channel##_volume(struct snd_kcontrol *kc, \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399) struct snd_ctl_elem_value *uc) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400) { \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401) struct snd_soc_dai *cpu_dai = snd_kcontrol_chip(kc); \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402) struct omap_mcbsp *mcbsp = snd_soc_dai_get_drvdata(cpu_dai); \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403) struct soc_mixer_control *mc = \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404) (struct soc_mixer_control *)kc->private_value; \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405) int max = mc->max; \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406) int min = mc->min; \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 407) int val = uc->value.integer.value[0]; \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 408) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 409) if (val < min || val > max) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 410) return -EINVAL; \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 411) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 412) /* OMAP McBSP implementation uses index values 0..4 */ \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 413) return omap_mcbsp_st_set_chgain(mcbsp, channel, val); \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 414) } \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 415) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 416) static int \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 417) omap_mcbsp_get_st_ch##channel##_volume(struct snd_kcontrol *kc, \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 418) struct snd_ctl_elem_value *uc) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 419) { \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 420) struct snd_soc_dai *cpu_dai = snd_kcontrol_chip(kc); \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 421) struct omap_mcbsp *mcbsp = snd_soc_dai_get_drvdata(cpu_dai); \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 422) s16 chgain; \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 423) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 424) if (omap_mcbsp_st_get_chgain(mcbsp, channel, &chgain)) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 425) return -EAGAIN; \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 426) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 427) uc->value.integer.value[0] = chgain; \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 428) return 0; \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 429) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 430)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 431) OMAP_MCBSP_ST_CHANNEL_VOLUME(0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 432) OMAP_MCBSP_ST_CHANNEL_VOLUME(1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 433)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 434) static int omap_mcbsp_st_put_mode(struct snd_kcontrol *kcontrol,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 435) struct snd_ctl_elem_value *ucontrol)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 436) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 437) struct snd_soc_dai *cpu_dai = snd_kcontrol_chip(kcontrol);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 438) struct omap_mcbsp *mcbsp = snd_soc_dai_get_drvdata(cpu_dai);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 439) u8 value = ucontrol->value.integer.value[0];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 440)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 441) if (value == omap_mcbsp_st_is_enabled(mcbsp))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 442) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 443)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 444) if (value)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 445) omap_mcbsp_st_enable(mcbsp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 446) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 447) omap_mcbsp_st_disable(mcbsp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 448)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 449) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 450) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 451)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 452) static int omap_mcbsp_st_get_mode(struct snd_kcontrol *kcontrol,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 453) struct snd_ctl_elem_value *ucontrol)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 454) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 455) struct snd_soc_dai *cpu_dai = snd_kcontrol_chip(kcontrol);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 456) struct omap_mcbsp *mcbsp = snd_soc_dai_get_drvdata(cpu_dai);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 457)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 458) ucontrol->value.integer.value[0] = omap_mcbsp_st_is_enabled(mcbsp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 459) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 460) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 461)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 462) #define OMAP_MCBSP_SOC_SINGLE_S16_EXT(xname, xmin, xmax, \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 463) xhandler_get, xhandler_put) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 464) { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 465) .info = omap_mcbsp_st_info_volsw, \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 466) .get = xhandler_get, .put = xhandler_put, \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 467) .private_value = (unsigned long)&(struct soc_mixer_control) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 468) {.min = xmin, .max = xmax} }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 469)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 470) #define OMAP_MCBSP_ST_CONTROLS(port) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 471) static const struct snd_kcontrol_new omap_mcbsp##port##_st_controls[] = { \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 472) SOC_SINGLE_EXT("McBSP" #port " Sidetone Switch", 1, 0, 1, 0, \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 473) omap_mcbsp_st_get_mode, omap_mcbsp_st_put_mode), \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 474) OMAP_MCBSP_SOC_SINGLE_S16_EXT("McBSP" #port " Sidetone Channel 0 Volume", \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 475) -32768, 32767, \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 476) omap_mcbsp_get_st_ch0_volume, \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 477) omap_mcbsp_set_st_ch0_volume), \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 478) OMAP_MCBSP_SOC_SINGLE_S16_EXT("McBSP" #port " Sidetone Channel 1 Volume", \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 479) -32768, 32767, \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 480) omap_mcbsp_get_st_ch1_volume, \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 481) omap_mcbsp_set_st_ch1_volume), \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 482) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 483)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 484) OMAP_MCBSP_ST_CONTROLS(2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 485) OMAP_MCBSP_ST_CONTROLS(3);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 486)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 487) int omap_mcbsp_st_add_controls(struct snd_soc_pcm_runtime *rtd, int port_id)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 488) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 489) struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 490) struct omap_mcbsp *mcbsp = snd_soc_dai_get_drvdata(cpu_dai);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 491)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 492) if (!mcbsp->st_data) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 493) dev_warn(mcbsp->dev, "No sidetone data for port\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 494) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 495) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 496)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 497) switch (port_id) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 498) case 2: /* McBSP 2 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 499) return snd_soc_add_dai_controls(cpu_dai,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 500) omap_mcbsp2_st_controls,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 501) ARRAY_SIZE(omap_mcbsp2_st_controls));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 502) case 3: /* McBSP 3 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 503) return snd_soc_add_dai_controls(cpu_dai,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 504) omap_mcbsp3_st_controls,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 505) ARRAY_SIZE(omap_mcbsp3_st_controls));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 506) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 507) dev_err(mcbsp->dev, "Port %d not supported\n", port_id);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 508) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 509) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 510)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 511) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 512) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 513) EXPORT_SYMBOL_GPL(omap_mcbsp_st_add_controls);