Orange Pi5 kernel

Deprecated Linux kernel 5.10.110 for OrangePi 5/5B/5+ boards

3 Commits   0 Branches   0 Tags
^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);