1*3117bb31SNicolin Chen /* 2*3117bb31SNicolin Chen * Freescale ASRC ALSA SoC Digital Audio Interface (DAI) driver 3*3117bb31SNicolin Chen * 4*3117bb31SNicolin Chen * Copyright (C) 2014 Freescale Semiconductor, Inc. 5*3117bb31SNicolin Chen * 6*3117bb31SNicolin Chen * Author: Nicolin Chen <nicoleotsuka@gmail.com> 7*3117bb31SNicolin Chen * 8*3117bb31SNicolin Chen * This file is licensed under the terms of the GNU General Public License 9*3117bb31SNicolin Chen * version 2. This program is licensed "as is" without any warranty of any 10*3117bb31SNicolin Chen * kind, whether express or implied. 11*3117bb31SNicolin Chen */ 12*3117bb31SNicolin Chen 13*3117bb31SNicolin Chen #include <linux/clk.h> 14*3117bb31SNicolin Chen #include <linux/delay.h> 15*3117bb31SNicolin Chen #include <linux/dma-mapping.h> 16*3117bb31SNicolin Chen #include <linux/module.h> 17*3117bb31SNicolin Chen #include <linux/of_platform.h> 18*3117bb31SNicolin Chen #include <linux/platform_data/dma-imx.h> 19*3117bb31SNicolin Chen #include <linux/pm_runtime.h> 20*3117bb31SNicolin Chen #include <sound/dmaengine_pcm.h> 21*3117bb31SNicolin Chen #include <sound/pcm_params.h> 22*3117bb31SNicolin Chen 23*3117bb31SNicolin Chen #include "fsl_asrc.h" 24*3117bb31SNicolin Chen 25*3117bb31SNicolin Chen #define IDEAL_RATIO_DECIMAL_DEPTH 26 26*3117bb31SNicolin Chen 27*3117bb31SNicolin Chen #define pair_err(fmt, ...) \ 28*3117bb31SNicolin Chen dev_err(&asrc_priv->pdev->dev, "Pair %c: " fmt, 'A' + index, ##__VA_ARGS__) 29*3117bb31SNicolin Chen 30*3117bb31SNicolin Chen #define pair_dbg(fmt, ...) \ 31*3117bb31SNicolin Chen dev_dbg(&asrc_priv->pdev->dev, "Pair %c: " fmt, 'A' + index, ##__VA_ARGS__) 32*3117bb31SNicolin Chen 33*3117bb31SNicolin Chen /* Sample rates are aligned with that defined in pcm.h file */ 34*3117bb31SNicolin Chen static const u8 process_option[][8][2] = { 35*3117bb31SNicolin Chen /* 32kHz 44.1kHz 48kHz 64kHz 88.2kHz 96kHz 176kHz 192kHz */ 36*3117bb31SNicolin Chen {{0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0},}, /* 5512Hz */ 37*3117bb31SNicolin Chen {{0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0},}, /* 8kHz */ 38*3117bb31SNicolin Chen {{0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0},}, /* 11025Hz */ 39*3117bb31SNicolin Chen {{0, 1}, {0, 1}, {0, 1}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0},}, /* 16kHz */ 40*3117bb31SNicolin Chen {{0, 1}, {0, 1}, {0, 1}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0},}, /* 22050Hz */ 41*3117bb31SNicolin Chen {{0, 1}, {0, 1}, {0, 1}, {0, 1}, {0, 1}, {0, 0}, {0, 0}, {0, 0},}, /* 32kHz */ 42*3117bb31SNicolin Chen {{0, 2}, {0, 1}, {0, 1}, {0, 1}, {0, 1}, {0, 1}, {0, 0}, {0, 0},}, /* 44.1kHz */ 43*3117bb31SNicolin Chen {{0, 2}, {0, 2}, {0, 1}, {0, 1}, {0, 1}, {0, 1}, {0, 0}, {0, 0},}, /* 48kHz */ 44*3117bb31SNicolin Chen {{1, 2}, {0, 2}, {0, 2}, {0, 1}, {0, 1}, {0, 1}, {0, 1}, {0, 0},}, /* 64kHz */ 45*3117bb31SNicolin Chen {{1, 2}, {1, 2}, {1, 2}, {1, 1}, {1, 1}, {1, 1}, {1, 1}, {1, 1},}, /* 88.2kHz */ 46*3117bb31SNicolin Chen {{1, 2}, {1, 2}, {1, 2}, {1, 1}, {1, 1}, {1, 1}, {1, 1}, {1, 1},}, /* 96kHz */ 47*3117bb31SNicolin Chen {{2, 2}, {2, 2}, {2, 2}, {2, 1}, {2, 1}, {2, 1}, {2, 1}, {2, 1},}, /* 176kHz */ 48*3117bb31SNicolin Chen {{2, 2}, {2, 2}, {2, 2}, {2, 1}, {2, 1}, {2, 1}, {2, 1}, {2, 1},}, /* 192kHz */ 49*3117bb31SNicolin Chen }; 50*3117bb31SNicolin Chen 51*3117bb31SNicolin Chen /* Corresponding to process_option */ 52*3117bb31SNicolin Chen static int supported_input_rate[] = { 53*3117bb31SNicolin Chen 5512, 8000, 11025, 16000, 22050, 32000, 44100, 48000, 64000, 88200, 54*3117bb31SNicolin Chen 96000, 176400, 192000, 55*3117bb31SNicolin Chen }; 56*3117bb31SNicolin Chen 57*3117bb31SNicolin Chen static int supported_asrc_rate[] = { 58*3117bb31SNicolin Chen 32000, 44100, 48000, 64000, 88200, 96000, 176400, 192000, 59*3117bb31SNicolin Chen }; 60*3117bb31SNicolin Chen 61*3117bb31SNicolin Chen /** 62*3117bb31SNicolin Chen * The following tables map the relationship between asrc_inclk/asrc_outclk in 63*3117bb31SNicolin Chen * fsl_asrc.h and the registers of ASRCSR 64*3117bb31SNicolin Chen */ 65*3117bb31SNicolin Chen static unsigned char input_clk_map_imx35[] = { 66*3117bb31SNicolin Chen 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 67*3117bb31SNicolin Chen }; 68*3117bb31SNicolin Chen 69*3117bb31SNicolin Chen static unsigned char output_clk_map_imx35[] = { 70*3117bb31SNicolin Chen 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 71*3117bb31SNicolin Chen }; 72*3117bb31SNicolin Chen 73*3117bb31SNicolin Chen /* i.MX53 uses the same map for input and output */ 74*3117bb31SNicolin Chen static unsigned char input_clk_map_imx53[] = { 75*3117bb31SNicolin Chen /* 0x0 0x1 0x2 0x3 0x4 0x5 0x6 0x7 0x8 0x9 0xa 0xb 0xc 0xd 0xe 0xf */ 76*3117bb31SNicolin Chen 0x0, 0x1, 0x2, 0x7, 0x4, 0x5, 0x6, 0x3, 0x8, 0x9, 0xa, 0xb, 0xc, 0xf, 0xe, 0xd, 77*3117bb31SNicolin Chen }; 78*3117bb31SNicolin Chen 79*3117bb31SNicolin Chen static unsigned char output_clk_map_imx53[] = { 80*3117bb31SNicolin Chen /* 0x0 0x1 0x2 0x3 0x4 0x5 0x6 0x7 0x8 0x9 0xa 0xb 0xc 0xd 0xe 0xf */ 81*3117bb31SNicolin Chen 0x8, 0x9, 0xa, 0x7, 0xc, 0x5, 0x6, 0xb, 0x0, 0x1, 0x2, 0x3, 0x4, 0xf, 0xe, 0xd, 82*3117bb31SNicolin Chen }; 83*3117bb31SNicolin Chen 84*3117bb31SNicolin Chen static unsigned char *clk_map[2]; 85*3117bb31SNicolin Chen 86*3117bb31SNicolin Chen /** 87*3117bb31SNicolin Chen * Request ASRC pair 88*3117bb31SNicolin Chen * 89*3117bb31SNicolin Chen * It assigns pair by the order of A->C->B because allocation of pair B, 90*3117bb31SNicolin Chen * within range [ANCA, ANCA+ANCB-1], depends on the channels of pair A 91*3117bb31SNicolin Chen * while pair A and pair C are comparatively independent. 92*3117bb31SNicolin Chen */ 93*3117bb31SNicolin Chen static int fsl_asrc_request_pair(int channels, struct fsl_asrc_pair *pair) 94*3117bb31SNicolin Chen { 95*3117bb31SNicolin Chen enum asrc_pair_index index = ASRC_INVALID_PAIR; 96*3117bb31SNicolin Chen struct fsl_asrc *asrc_priv = pair->asrc_priv; 97*3117bb31SNicolin Chen struct device *dev = &asrc_priv->pdev->dev; 98*3117bb31SNicolin Chen unsigned long lock_flags; 99*3117bb31SNicolin Chen int i, ret = 0; 100*3117bb31SNicolin Chen 101*3117bb31SNicolin Chen spin_lock_irqsave(&asrc_priv->lock, lock_flags); 102*3117bb31SNicolin Chen 103*3117bb31SNicolin Chen for (i = ASRC_PAIR_A; i < ASRC_PAIR_MAX_NUM; i++) { 104*3117bb31SNicolin Chen if (asrc_priv->pair[i] != NULL) 105*3117bb31SNicolin Chen continue; 106*3117bb31SNicolin Chen 107*3117bb31SNicolin Chen index = i; 108*3117bb31SNicolin Chen 109*3117bb31SNicolin Chen if (i != ASRC_PAIR_B) 110*3117bb31SNicolin Chen break; 111*3117bb31SNicolin Chen } 112*3117bb31SNicolin Chen 113*3117bb31SNicolin Chen if (index == ASRC_INVALID_PAIR) { 114*3117bb31SNicolin Chen dev_err(dev, "all pairs are busy now\n"); 115*3117bb31SNicolin Chen ret = -EBUSY; 116*3117bb31SNicolin Chen } else if (asrc_priv->channel_avail < channels) { 117*3117bb31SNicolin Chen dev_err(dev, "can't afford required channels: %d\n", channels); 118*3117bb31SNicolin Chen ret = -EINVAL; 119*3117bb31SNicolin Chen } else { 120*3117bb31SNicolin Chen asrc_priv->channel_avail -= channels; 121*3117bb31SNicolin Chen asrc_priv->pair[index] = pair; 122*3117bb31SNicolin Chen pair->channels = channels; 123*3117bb31SNicolin Chen pair->index = index; 124*3117bb31SNicolin Chen } 125*3117bb31SNicolin Chen 126*3117bb31SNicolin Chen spin_unlock_irqrestore(&asrc_priv->lock, lock_flags); 127*3117bb31SNicolin Chen 128*3117bb31SNicolin Chen return ret; 129*3117bb31SNicolin Chen } 130*3117bb31SNicolin Chen 131*3117bb31SNicolin Chen /** 132*3117bb31SNicolin Chen * Release ASRC pair 133*3117bb31SNicolin Chen * 134*3117bb31SNicolin Chen * It clears the resource from asrc_priv and releases the occupied channels. 135*3117bb31SNicolin Chen */ 136*3117bb31SNicolin Chen static void fsl_asrc_release_pair(struct fsl_asrc_pair *pair) 137*3117bb31SNicolin Chen { 138*3117bb31SNicolin Chen struct fsl_asrc *asrc_priv = pair->asrc_priv; 139*3117bb31SNicolin Chen enum asrc_pair_index index = pair->index; 140*3117bb31SNicolin Chen unsigned long lock_flags; 141*3117bb31SNicolin Chen 142*3117bb31SNicolin Chen /* Make sure the pair is disabled */ 143*3117bb31SNicolin Chen regmap_update_bits(asrc_priv->regmap, REG_ASRCTR, 144*3117bb31SNicolin Chen ASRCTR_ASRCEi_MASK(index), 0); 145*3117bb31SNicolin Chen 146*3117bb31SNicolin Chen spin_lock_irqsave(&asrc_priv->lock, lock_flags); 147*3117bb31SNicolin Chen 148*3117bb31SNicolin Chen asrc_priv->channel_avail += pair->channels; 149*3117bb31SNicolin Chen asrc_priv->pair[index] = NULL; 150*3117bb31SNicolin Chen pair->error = 0; 151*3117bb31SNicolin Chen 152*3117bb31SNicolin Chen spin_unlock_irqrestore(&asrc_priv->lock, lock_flags); 153*3117bb31SNicolin Chen } 154*3117bb31SNicolin Chen 155*3117bb31SNicolin Chen /** 156*3117bb31SNicolin Chen * Configure input and output thresholds 157*3117bb31SNicolin Chen */ 158*3117bb31SNicolin Chen static void fsl_asrc_set_watermarks(struct fsl_asrc_pair *pair, u32 in, u32 out) 159*3117bb31SNicolin Chen { 160*3117bb31SNicolin Chen struct fsl_asrc *asrc_priv = pair->asrc_priv; 161*3117bb31SNicolin Chen enum asrc_pair_index index = pair->index; 162*3117bb31SNicolin Chen 163*3117bb31SNicolin Chen regmap_update_bits(asrc_priv->regmap, REG_ASRMCR(index), 164*3117bb31SNicolin Chen ASRMCRi_EXTTHRSHi_MASK | 165*3117bb31SNicolin Chen ASRMCRi_INFIFO_THRESHOLD_MASK | 166*3117bb31SNicolin Chen ASRMCRi_OUTFIFO_THRESHOLD_MASK, 167*3117bb31SNicolin Chen ASRMCRi_EXTTHRSHi | 168*3117bb31SNicolin Chen ASRMCRi_INFIFO_THRESHOLD(in) | 169*3117bb31SNicolin Chen ASRMCRi_OUTFIFO_THRESHOLD(out)); 170*3117bb31SNicolin Chen } 171*3117bb31SNicolin Chen 172*3117bb31SNicolin Chen /** 173*3117bb31SNicolin Chen * Calculate the total divisor between asrck clock rate and sample rate 174*3117bb31SNicolin Chen * 175*3117bb31SNicolin Chen * It follows the formula clk_rate = samplerate * (2 ^ prescaler) * divider 176*3117bb31SNicolin Chen */ 177*3117bb31SNicolin Chen static u32 fsl_asrc_cal_asrck_divisor(struct fsl_asrc_pair *pair, u32 div) 178*3117bb31SNicolin Chen { 179*3117bb31SNicolin Chen u32 ps; 180*3117bb31SNicolin Chen 181*3117bb31SNicolin Chen /* Calculate the divisors: prescaler [2^0, 2^7], divder [1, 8] */ 182*3117bb31SNicolin Chen for (ps = 0; div > 8; ps++) 183*3117bb31SNicolin Chen div >>= 1; 184*3117bb31SNicolin Chen 185*3117bb31SNicolin Chen return ((div - 1) << ASRCDRi_AxCPi_WIDTH) | ps; 186*3117bb31SNicolin Chen } 187*3117bb31SNicolin Chen 188*3117bb31SNicolin Chen /** 189*3117bb31SNicolin Chen * Calculate and set the ratio for Ideal Ratio mode only 190*3117bb31SNicolin Chen * 191*3117bb31SNicolin Chen * The ratio is a 32-bit fixed point value with 26 fractional bits. 192*3117bb31SNicolin Chen */ 193*3117bb31SNicolin Chen static int fsl_asrc_set_ideal_ratio(struct fsl_asrc_pair *pair, 194*3117bb31SNicolin Chen int inrate, int outrate) 195*3117bb31SNicolin Chen { 196*3117bb31SNicolin Chen struct fsl_asrc *asrc_priv = pair->asrc_priv; 197*3117bb31SNicolin Chen enum asrc_pair_index index = pair->index; 198*3117bb31SNicolin Chen unsigned long ratio; 199*3117bb31SNicolin Chen int i; 200*3117bb31SNicolin Chen 201*3117bb31SNicolin Chen if (!outrate) { 202*3117bb31SNicolin Chen pair_err("output rate should not be zero\n"); 203*3117bb31SNicolin Chen return -EINVAL; 204*3117bb31SNicolin Chen } 205*3117bb31SNicolin Chen 206*3117bb31SNicolin Chen /* Calculate the intergal part of the ratio */ 207*3117bb31SNicolin Chen ratio = (inrate / outrate) << IDEAL_RATIO_DECIMAL_DEPTH; 208*3117bb31SNicolin Chen 209*3117bb31SNicolin Chen /* ... and then the 26 depth decimal part */ 210*3117bb31SNicolin Chen inrate %= outrate; 211*3117bb31SNicolin Chen 212*3117bb31SNicolin Chen for (i = 1; i <= IDEAL_RATIO_DECIMAL_DEPTH; i++) { 213*3117bb31SNicolin Chen inrate <<= 1; 214*3117bb31SNicolin Chen 215*3117bb31SNicolin Chen if (inrate < outrate) 216*3117bb31SNicolin Chen continue; 217*3117bb31SNicolin Chen 218*3117bb31SNicolin Chen ratio |= 1 << (IDEAL_RATIO_DECIMAL_DEPTH - i); 219*3117bb31SNicolin Chen inrate -= outrate; 220*3117bb31SNicolin Chen 221*3117bb31SNicolin Chen if (!inrate) 222*3117bb31SNicolin Chen break; 223*3117bb31SNicolin Chen } 224*3117bb31SNicolin Chen 225*3117bb31SNicolin Chen regmap_write(asrc_priv->regmap, REG_ASRIDRL(index), ratio); 226*3117bb31SNicolin Chen regmap_write(asrc_priv->regmap, REG_ASRIDRH(index), ratio >> 24); 227*3117bb31SNicolin Chen 228*3117bb31SNicolin Chen return 0; 229*3117bb31SNicolin Chen } 230*3117bb31SNicolin Chen 231*3117bb31SNicolin Chen /** 232*3117bb31SNicolin Chen * Configure the assigned ASRC pair 233*3117bb31SNicolin Chen * 234*3117bb31SNicolin Chen * It configures those ASRC registers according to a configuration instance 235*3117bb31SNicolin Chen * of struct asrc_config which includes in/output sample rate, width, channel 236*3117bb31SNicolin Chen * and clock settings. 237*3117bb31SNicolin Chen */ 238*3117bb31SNicolin Chen static int fsl_asrc_config_pair(struct fsl_asrc_pair *pair) 239*3117bb31SNicolin Chen { 240*3117bb31SNicolin Chen struct asrc_config *config = pair->config; 241*3117bb31SNicolin Chen struct fsl_asrc *asrc_priv = pair->asrc_priv; 242*3117bb31SNicolin Chen enum asrc_pair_index index = pair->index; 243*3117bb31SNicolin Chen u32 inrate = config->input_sample_rate, indiv; 244*3117bb31SNicolin Chen u32 outrate = config->output_sample_rate, outdiv; 245*3117bb31SNicolin Chen bool ideal = config->inclk == INCLK_NONE; 246*3117bb31SNicolin Chen u32 clk_index[2], div[2]; 247*3117bb31SNicolin Chen int in, out, channels; 248*3117bb31SNicolin Chen struct clk *clk; 249*3117bb31SNicolin Chen 250*3117bb31SNicolin Chen if (!config) { 251*3117bb31SNicolin Chen pair_err("invalid pair config\n"); 252*3117bb31SNicolin Chen return -EINVAL; 253*3117bb31SNicolin Chen } 254*3117bb31SNicolin Chen 255*3117bb31SNicolin Chen /* Validate channels */ 256*3117bb31SNicolin Chen if (config->channel_num < 1 || config->channel_num > 10) { 257*3117bb31SNicolin Chen pair_err("does not support %d channels\n", config->channel_num); 258*3117bb31SNicolin Chen return -EINVAL; 259*3117bb31SNicolin Chen } 260*3117bb31SNicolin Chen 261*3117bb31SNicolin Chen /* Validate output width */ 262*3117bb31SNicolin Chen if (config->output_word_width == ASRC_WIDTH_8_BIT) { 263*3117bb31SNicolin Chen pair_err("does not support 8bit width output\n"); 264*3117bb31SNicolin Chen return -EINVAL; 265*3117bb31SNicolin Chen } 266*3117bb31SNicolin Chen 267*3117bb31SNicolin Chen /* Validate input and output sample rates */ 268*3117bb31SNicolin Chen for (in = 0; in < ARRAY_SIZE(supported_input_rate); in++) 269*3117bb31SNicolin Chen if (inrate == supported_input_rate[in]) 270*3117bb31SNicolin Chen break; 271*3117bb31SNicolin Chen 272*3117bb31SNicolin Chen if (in == ARRAY_SIZE(supported_input_rate)) { 273*3117bb31SNicolin Chen pair_err("unsupported input sample rate: %dHz\n", inrate); 274*3117bb31SNicolin Chen return -EINVAL; 275*3117bb31SNicolin Chen } 276*3117bb31SNicolin Chen 277*3117bb31SNicolin Chen for (out = 0; out < ARRAY_SIZE(supported_asrc_rate); out++) 278*3117bb31SNicolin Chen if (outrate == supported_asrc_rate[out]) 279*3117bb31SNicolin Chen break; 280*3117bb31SNicolin Chen 281*3117bb31SNicolin Chen if (out == ARRAY_SIZE(supported_asrc_rate)) { 282*3117bb31SNicolin Chen pair_err("unsupported output sample rate: %dHz\n", outrate); 283*3117bb31SNicolin Chen return -EINVAL; 284*3117bb31SNicolin Chen } 285*3117bb31SNicolin Chen 286*3117bb31SNicolin Chen /* Validate input and output clock sources */ 287*3117bb31SNicolin Chen clk_index[IN] = clk_map[IN][config->inclk]; 288*3117bb31SNicolin Chen clk_index[OUT] = clk_map[OUT][config->outclk]; 289*3117bb31SNicolin Chen 290*3117bb31SNicolin Chen /* We only have output clock for ideal ratio mode */ 291*3117bb31SNicolin Chen clk = asrc_priv->asrck_clk[clk_index[ideal ? OUT : IN]]; 292*3117bb31SNicolin Chen 293*3117bb31SNicolin Chen div[IN] = clk_get_rate(clk) / inrate; 294*3117bb31SNicolin Chen if (div[IN] == 0) { 295*3117bb31SNicolin Chen pair_err("failed to support input sample rate %dHz by asrck_%x\n", 296*3117bb31SNicolin Chen inrate, clk_index[ideal ? OUT : IN]); 297*3117bb31SNicolin Chen return -EINVAL; 298*3117bb31SNicolin Chen } 299*3117bb31SNicolin Chen 300*3117bb31SNicolin Chen clk = asrc_priv->asrck_clk[clk_index[OUT]]; 301*3117bb31SNicolin Chen 302*3117bb31SNicolin Chen /* Use fixed output rate for Ideal Ratio mode (INCLK_NONE) */ 303*3117bb31SNicolin Chen if (ideal) 304*3117bb31SNicolin Chen div[OUT] = clk_get_rate(clk) / IDEAL_RATIO_RATE; 305*3117bb31SNicolin Chen else 306*3117bb31SNicolin Chen div[OUT] = clk_get_rate(clk) / outrate; 307*3117bb31SNicolin Chen 308*3117bb31SNicolin Chen if (div[OUT] == 0) { 309*3117bb31SNicolin Chen pair_err("failed to support output sample rate %dHz by asrck_%x\n", 310*3117bb31SNicolin Chen outrate, clk_index[OUT]); 311*3117bb31SNicolin Chen return -EINVAL; 312*3117bb31SNicolin Chen } 313*3117bb31SNicolin Chen 314*3117bb31SNicolin Chen /* Set the channel number */ 315*3117bb31SNicolin Chen channels = config->channel_num; 316*3117bb31SNicolin Chen 317*3117bb31SNicolin Chen if (asrc_priv->channel_bits < 4) 318*3117bb31SNicolin Chen channels /= 2; 319*3117bb31SNicolin Chen 320*3117bb31SNicolin Chen /* Update channels for current pair */ 321*3117bb31SNicolin Chen regmap_update_bits(asrc_priv->regmap, REG_ASRCNCR, 322*3117bb31SNicolin Chen ASRCNCR_ANCi_MASK(index, asrc_priv->channel_bits), 323*3117bb31SNicolin Chen ASRCNCR_ANCi(index, channels, asrc_priv->channel_bits)); 324*3117bb31SNicolin Chen 325*3117bb31SNicolin Chen /* Default setting: Automatic selection for processing mode */ 326*3117bb31SNicolin Chen regmap_update_bits(asrc_priv->regmap, REG_ASRCTR, 327*3117bb31SNicolin Chen ASRCTR_ATSi_MASK(index), ASRCTR_ATS(index)); 328*3117bb31SNicolin Chen regmap_update_bits(asrc_priv->regmap, REG_ASRCTR, 329*3117bb31SNicolin Chen ASRCTR_USRi_MASK(index), 0); 330*3117bb31SNicolin Chen 331*3117bb31SNicolin Chen /* Set the input and output clock sources */ 332*3117bb31SNicolin Chen regmap_update_bits(asrc_priv->regmap, REG_ASRCSR, 333*3117bb31SNicolin Chen ASRCSR_AICSi_MASK(index) | ASRCSR_AOCSi_MASK(index), 334*3117bb31SNicolin Chen ASRCSR_AICS(index, clk_index[IN]) | 335*3117bb31SNicolin Chen ASRCSR_AOCS(index, clk_index[OUT])); 336*3117bb31SNicolin Chen 337*3117bb31SNicolin Chen /* Calculate the input clock divisors */ 338*3117bb31SNicolin Chen indiv = fsl_asrc_cal_asrck_divisor(pair, div[IN]); 339*3117bb31SNicolin Chen outdiv = fsl_asrc_cal_asrck_divisor(pair, div[OUT]); 340*3117bb31SNicolin Chen 341*3117bb31SNicolin Chen /* Suppose indiv and outdiv includes prescaler, so add its MASK too */ 342*3117bb31SNicolin Chen regmap_update_bits(asrc_priv->regmap, REG_ASRCDR(index), 343*3117bb31SNicolin Chen ASRCDRi_AOCPi_MASK(index) | ASRCDRi_AICPi_MASK(index) | 344*3117bb31SNicolin Chen ASRCDRi_AOCDi_MASK(index) | ASRCDRi_AICDi_MASK(index), 345*3117bb31SNicolin Chen ASRCDRi_AOCP(index, outdiv) | ASRCDRi_AICP(index, indiv)); 346*3117bb31SNicolin Chen 347*3117bb31SNicolin Chen /* Implement word_width configurations */ 348*3117bb31SNicolin Chen regmap_update_bits(asrc_priv->regmap, REG_ASRMCR1(index), 349*3117bb31SNicolin Chen ASRMCR1i_OW16_MASK | ASRMCR1i_IWD_MASK, 350*3117bb31SNicolin Chen ASRMCR1i_OW16(config->output_word_width) | 351*3117bb31SNicolin Chen ASRMCR1i_IWD(config->input_word_width)); 352*3117bb31SNicolin Chen 353*3117bb31SNicolin Chen /* Enable BUFFER STALL */ 354*3117bb31SNicolin Chen regmap_update_bits(asrc_priv->regmap, REG_ASRMCR(index), 355*3117bb31SNicolin Chen ASRMCRi_BUFSTALLi_MASK, ASRMCRi_BUFSTALLi); 356*3117bb31SNicolin Chen 357*3117bb31SNicolin Chen /* Set default thresholds for input and output FIFO */ 358*3117bb31SNicolin Chen fsl_asrc_set_watermarks(pair, ASRC_INPUTFIFO_THRESHOLD, 359*3117bb31SNicolin Chen ASRC_INPUTFIFO_THRESHOLD); 360*3117bb31SNicolin Chen 361*3117bb31SNicolin Chen /* Configure the followings only for Ideal Ratio mode */ 362*3117bb31SNicolin Chen if (!ideal) 363*3117bb31SNicolin Chen return 0; 364*3117bb31SNicolin Chen 365*3117bb31SNicolin Chen /* Clear ASTSx bit to use Ideal Ratio mode */ 366*3117bb31SNicolin Chen regmap_update_bits(asrc_priv->regmap, REG_ASRCTR, 367*3117bb31SNicolin Chen ASRCTR_ATSi_MASK(index), 0); 368*3117bb31SNicolin Chen 369*3117bb31SNicolin Chen /* Enable Ideal Ratio mode */ 370*3117bb31SNicolin Chen regmap_update_bits(asrc_priv->regmap, REG_ASRCTR, 371*3117bb31SNicolin Chen ASRCTR_IDRi_MASK(index) | ASRCTR_USRi_MASK(index), 372*3117bb31SNicolin Chen ASRCTR_IDR(index) | ASRCTR_USR(index)); 373*3117bb31SNicolin Chen 374*3117bb31SNicolin Chen /* Apply configurations for pre- and post-processing */ 375*3117bb31SNicolin Chen regmap_update_bits(asrc_priv->regmap, REG_ASRCFG, 376*3117bb31SNicolin Chen ASRCFG_PREMODi_MASK(index) | ASRCFG_POSTMODi_MASK(index), 377*3117bb31SNicolin Chen ASRCFG_PREMOD(index, process_option[in][out][0]) | 378*3117bb31SNicolin Chen ASRCFG_POSTMOD(index, process_option[in][out][1])); 379*3117bb31SNicolin Chen 380*3117bb31SNicolin Chen return fsl_asrc_set_ideal_ratio(pair, inrate, outrate); 381*3117bb31SNicolin Chen } 382*3117bb31SNicolin Chen 383*3117bb31SNicolin Chen /** 384*3117bb31SNicolin Chen * Start the assigned ASRC pair 385*3117bb31SNicolin Chen * 386*3117bb31SNicolin Chen * It enables the assigned pair and makes it stopped at the stall level. 387*3117bb31SNicolin Chen */ 388*3117bb31SNicolin Chen static void fsl_asrc_start_pair(struct fsl_asrc_pair *pair) 389*3117bb31SNicolin Chen { 390*3117bb31SNicolin Chen struct fsl_asrc *asrc_priv = pair->asrc_priv; 391*3117bb31SNicolin Chen enum asrc_pair_index index = pair->index; 392*3117bb31SNicolin Chen int reg, retry = 10, i; 393*3117bb31SNicolin Chen 394*3117bb31SNicolin Chen /* Enable the current pair */ 395*3117bb31SNicolin Chen regmap_update_bits(asrc_priv->regmap, REG_ASRCTR, 396*3117bb31SNicolin Chen ASRCTR_ASRCEi_MASK(index), ASRCTR_ASRCE(index)); 397*3117bb31SNicolin Chen 398*3117bb31SNicolin Chen /* Wait for status of initialization */ 399*3117bb31SNicolin Chen do { 400*3117bb31SNicolin Chen udelay(5); 401*3117bb31SNicolin Chen regmap_read(asrc_priv->regmap, REG_ASRCFG, ®); 402*3117bb31SNicolin Chen reg &= ASRCFG_INIRQi_MASK(index); 403*3117bb31SNicolin Chen } while (!reg && --retry); 404*3117bb31SNicolin Chen 405*3117bb31SNicolin Chen /* Make the input fifo to ASRC STALL level */ 406*3117bb31SNicolin Chen regmap_read(asrc_priv->regmap, REG_ASRCNCR, ®); 407*3117bb31SNicolin Chen for (i = 0; i < pair->channels * 4; i++) 408*3117bb31SNicolin Chen regmap_write(asrc_priv->regmap, REG_ASRDI(index), 0); 409*3117bb31SNicolin Chen 410*3117bb31SNicolin Chen /* Enable overload interrupt */ 411*3117bb31SNicolin Chen regmap_write(asrc_priv->regmap, REG_ASRIER, ASRIER_AOLIE); 412*3117bb31SNicolin Chen } 413*3117bb31SNicolin Chen 414*3117bb31SNicolin Chen /** 415*3117bb31SNicolin Chen * Stop the assigned ASRC pair 416*3117bb31SNicolin Chen */ 417*3117bb31SNicolin Chen static void fsl_asrc_stop_pair(struct fsl_asrc_pair *pair) 418*3117bb31SNicolin Chen { 419*3117bb31SNicolin Chen struct fsl_asrc *asrc_priv = pair->asrc_priv; 420*3117bb31SNicolin Chen enum asrc_pair_index index = pair->index; 421*3117bb31SNicolin Chen 422*3117bb31SNicolin Chen /* Stop the current pair */ 423*3117bb31SNicolin Chen regmap_update_bits(asrc_priv->regmap, REG_ASRCTR, 424*3117bb31SNicolin Chen ASRCTR_ASRCEi_MASK(index), 0); 425*3117bb31SNicolin Chen } 426*3117bb31SNicolin Chen 427*3117bb31SNicolin Chen /** 428*3117bb31SNicolin Chen * Get DMA channel according to the pair and direction. 429*3117bb31SNicolin Chen */ 430*3117bb31SNicolin Chen struct dma_chan *fsl_asrc_get_dma_channel(struct fsl_asrc_pair *pair, bool dir) 431*3117bb31SNicolin Chen { 432*3117bb31SNicolin Chen struct fsl_asrc *asrc_priv = pair->asrc_priv; 433*3117bb31SNicolin Chen enum asrc_pair_index index = pair->index; 434*3117bb31SNicolin Chen char name[4]; 435*3117bb31SNicolin Chen 436*3117bb31SNicolin Chen sprintf(name, "%cx%c", dir == IN ? 'r' : 't', index + 'a'); 437*3117bb31SNicolin Chen 438*3117bb31SNicolin Chen return dma_request_slave_channel(&asrc_priv->pdev->dev, name); 439*3117bb31SNicolin Chen } 440*3117bb31SNicolin Chen EXPORT_SYMBOL_GPL(fsl_asrc_get_dma_channel); 441*3117bb31SNicolin Chen 442*3117bb31SNicolin Chen static int fsl_asrc_dai_hw_params(struct snd_pcm_substream *substream, 443*3117bb31SNicolin Chen struct snd_pcm_hw_params *params, 444*3117bb31SNicolin Chen struct snd_soc_dai *dai) 445*3117bb31SNicolin Chen { 446*3117bb31SNicolin Chen struct fsl_asrc *asrc_priv = snd_soc_dai_get_drvdata(dai); 447*3117bb31SNicolin Chen int width = snd_pcm_format_width(params_format(params)); 448*3117bb31SNicolin Chen struct snd_pcm_runtime *runtime = substream->runtime; 449*3117bb31SNicolin Chen struct fsl_asrc_pair *pair = runtime->private_data; 450*3117bb31SNicolin Chen unsigned int channels = params_channels(params); 451*3117bb31SNicolin Chen unsigned int rate = params_rate(params); 452*3117bb31SNicolin Chen struct asrc_config config; 453*3117bb31SNicolin Chen int word_width, ret; 454*3117bb31SNicolin Chen 455*3117bb31SNicolin Chen ret = fsl_asrc_request_pair(channels, pair); 456*3117bb31SNicolin Chen if (ret) { 457*3117bb31SNicolin Chen dev_err(dai->dev, "fail to request asrc pair\n"); 458*3117bb31SNicolin Chen return ret; 459*3117bb31SNicolin Chen } 460*3117bb31SNicolin Chen 461*3117bb31SNicolin Chen pair->config = &config; 462*3117bb31SNicolin Chen 463*3117bb31SNicolin Chen if (width == 16) 464*3117bb31SNicolin Chen width = ASRC_WIDTH_16_BIT; 465*3117bb31SNicolin Chen else 466*3117bb31SNicolin Chen width = ASRC_WIDTH_24_BIT; 467*3117bb31SNicolin Chen 468*3117bb31SNicolin Chen if (asrc_priv->asrc_width == 16) 469*3117bb31SNicolin Chen word_width = ASRC_WIDTH_16_BIT; 470*3117bb31SNicolin Chen else 471*3117bb31SNicolin Chen word_width = ASRC_WIDTH_24_BIT; 472*3117bb31SNicolin Chen 473*3117bb31SNicolin Chen config.pair = pair->index; 474*3117bb31SNicolin Chen config.channel_num = channels; 475*3117bb31SNicolin Chen config.inclk = INCLK_NONE; 476*3117bb31SNicolin Chen config.outclk = OUTCLK_ASRCK1_CLK; 477*3117bb31SNicolin Chen 478*3117bb31SNicolin Chen if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { 479*3117bb31SNicolin Chen config.input_word_width = width; 480*3117bb31SNicolin Chen config.output_word_width = word_width; 481*3117bb31SNicolin Chen config.input_sample_rate = rate; 482*3117bb31SNicolin Chen config.output_sample_rate = asrc_priv->asrc_rate; 483*3117bb31SNicolin Chen } else { 484*3117bb31SNicolin Chen config.input_word_width = word_width; 485*3117bb31SNicolin Chen config.output_word_width = width; 486*3117bb31SNicolin Chen config.input_sample_rate = asrc_priv->asrc_rate; 487*3117bb31SNicolin Chen config.output_sample_rate = rate; 488*3117bb31SNicolin Chen } 489*3117bb31SNicolin Chen 490*3117bb31SNicolin Chen ret = fsl_asrc_config_pair(pair); 491*3117bb31SNicolin Chen if (ret) { 492*3117bb31SNicolin Chen dev_err(dai->dev, "fail to config asrc pair\n"); 493*3117bb31SNicolin Chen return ret; 494*3117bb31SNicolin Chen } 495*3117bb31SNicolin Chen 496*3117bb31SNicolin Chen return 0; 497*3117bb31SNicolin Chen } 498*3117bb31SNicolin Chen 499*3117bb31SNicolin Chen static int fsl_asrc_dai_hw_free(struct snd_pcm_substream *substream, 500*3117bb31SNicolin Chen struct snd_soc_dai *dai) 501*3117bb31SNicolin Chen { 502*3117bb31SNicolin Chen struct snd_pcm_runtime *runtime = substream->runtime; 503*3117bb31SNicolin Chen struct fsl_asrc_pair *pair = runtime->private_data; 504*3117bb31SNicolin Chen 505*3117bb31SNicolin Chen if (pair) 506*3117bb31SNicolin Chen fsl_asrc_release_pair(pair); 507*3117bb31SNicolin Chen 508*3117bb31SNicolin Chen return 0; 509*3117bb31SNicolin Chen } 510*3117bb31SNicolin Chen 511*3117bb31SNicolin Chen static int fsl_asrc_dai_trigger(struct snd_pcm_substream *substream, int cmd, 512*3117bb31SNicolin Chen struct snd_soc_dai *dai) 513*3117bb31SNicolin Chen { 514*3117bb31SNicolin Chen struct snd_pcm_runtime *runtime = substream->runtime; 515*3117bb31SNicolin Chen struct fsl_asrc_pair *pair = runtime->private_data; 516*3117bb31SNicolin Chen 517*3117bb31SNicolin Chen switch (cmd) { 518*3117bb31SNicolin Chen case SNDRV_PCM_TRIGGER_START: 519*3117bb31SNicolin Chen case SNDRV_PCM_TRIGGER_RESUME: 520*3117bb31SNicolin Chen case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: 521*3117bb31SNicolin Chen fsl_asrc_start_pair(pair); 522*3117bb31SNicolin Chen break; 523*3117bb31SNicolin Chen case SNDRV_PCM_TRIGGER_STOP: 524*3117bb31SNicolin Chen case SNDRV_PCM_TRIGGER_SUSPEND: 525*3117bb31SNicolin Chen case SNDRV_PCM_TRIGGER_PAUSE_PUSH: 526*3117bb31SNicolin Chen fsl_asrc_stop_pair(pair); 527*3117bb31SNicolin Chen break; 528*3117bb31SNicolin Chen default: 529*3117bb31SNicolin Chen return -EINVAL; 530*3117bb31SNicolin Chen } 531*3117bb31SNicolin Chen 532*3117bb31SNicolin Chen return 0; 533*3117bb31SNicolin Chen } 534*3117bb31SNicolin Chen 535*3117bb31SNicolin Chen static struct snd_soc_dai_ops fsl_asrc_dai_ops = { 536*3117bb31SNicolin Chen .hw_params = fsl_asrc_dai_hw_params, 537*3117bb31SNicolin Chen .hw_free = fsl_asrc_dai_hw_free, 538*3117bb31SNicolin Chen .trigger = fsl_asrc_dai_trigger, 539*3117bb31SNicolin Chen }; 540*3117bb31SNicolin Chen 541*3117bb31SNicolin Chen static int fsl_asrc_dai_probe(struct snd_soc_dai *dai) 542*3117bb31SNicolin Chen { 543*3117bb31SNicolin Chen struct fsl_asrc *asrc_priv = snd_soc_dai_get_drvdata(dai); 544*3117bb31SNicolin Chen 545*3117bb31SNicolin Chen snd_soc_dai_init_dma_data(dai, &asrc_priv->dma_params_tx, 546*3117bb31SNicolin Chen &asrc_priv->dma_params_rx); 547*3117bb31SNicolin Chen 548*3117bb31SNicolin Chen return 0; 549*3117bb31SNicolin Chen } 550*3117bb31SNicolin Chen 551*3117bb31SNicolin Chen #define FSL_ASRC_RATES SNDRV_PCM_RATE_8000_192000 552*3117bb31SNicolin Chen #define FSL_ASRC_FORMATS (SNDRV_PCM_FMTBIT_S24_LE | \ 553*3117bb31SNicolin Chen SNDRV_PCM_FMTBIT_S16_LE | \ 554*3117bb31SNicolin Chen SNDRV_PCM_FORMAT_S20_3LE) 555*3117bb31SNicolin Chen 556*3117bb31SNicolin Chen static struct snd_soc_dai_driver fsl_asrc_dai = { 557*3117bb31SNicolin Chen .probe = fsl_asrc_dai_probe, 558*3117bb31SNicolin Chen .playback = { 559*3117bb31SNicolin Chen .stream_name = "ASRC-Playback", 560*3117bb31SNicolin Chen .channels_min = 1, 561*3117bb31SNicolin Chen .channels_max = 10, 562*3117bb31SNicolin Chen .rates = FSL_ASRC_RATES, 563*3117bb31SNicolin Chen .formats = FSL_ASRC_FORMATS, 564*3117bb31SNicolin Chen }, 565*3117bb31SNicolin Chen .capture = { 566*3117bb31SNicolin Chen .stream_name = "ASRC-Capture", 567*3117bb31SNicolin Chen .channels_min = 1, 568*3117bb31SNicolin Chen .channels_max = 10, 569*3117bb31SNicolin Chen .rates = FSL_ASRC_RATES, 570*3117bb31SNicolin Chen .formats = FSL_ASRC_FORMATS, 571*3117bb31SNicolin Chen }, 572*3117bb31SNicolin Chen .ops = &fsl_asrc_dai_ops, 573*3117bb31SNicolin Chen }; 574*3117bb31SNicolin Chen 575*3117bb31SNicolin Chen static const struct snd_soc_component_driver fsl_asrc_component = { 576*3117bb31SNicolin Chen .name = "fsl-asrc-dai", 577*3117bb31SNicolin Chen }; 578*3117bb31SNicolin Chen 579*3117bb31SNicolin Chen static bool fsl_asrc_readable_reg(struct device *dev, unsigned int reg) 580*3117bb31SNicolin Chen { 581*3117bb31SNicolin Chen switch (reg) { 582*3117bb31SNicolin Chen case REG_ASRCTR: 583*3117bb31SNicolin Chen case REG_ASRIER: 584*3117bb31SNicolin Chen case REG_ASRCNCR: 585*3117bb31SNicolin Chen case REG_ASRCFG: 586*3117bb31SNicolin Chen case REG_ASRCSR: 587*3117bb31SNicolin Chen case REG_ASRCDR1: 588*3117bb31SNicolin Chen case REG_ASRCDR2: 589*3117bb31SNicolin Chen case REG_ASRSTR: 590*3117bb31SNicolin Chen case REG_ASRPM1: 591*3117bb31SNicolin Chen case REG_ASRPM2: 592*3117bb31SNicolin Chen case REG_ASRPM3: 593*3117bb31SNicolin Chen case REG_ASRPM4: 594*3117bb31SNicolin Chen case REG_ASRPM5: 595*3117bb31SNicolin Chen case REG_ASRTFR1: 596*3117bb31SNicolin Chen case REG_ASRCCR: 597*3117bb31SNicolin Chen case REG_ASRDOA: 598*3117bb31SNicolin Chen case REG_ASRDOB: 599*3117bb31SNicolin Chen case REG_ASRDOC: 600*3117bb31SNicolin Chen case REG_ASRIDRHA: 601*3117bb31SNicolin Chen case REG_ASRIDRLA: 602*3117bb31SNicolin Chen case REG_ASRIDRHB: 603*3117bb31SNicolin Chen case REG_ASRIDRLB: 604*3117bb31SNicolin Chen case REG_ASRIDRHC: 605*3117bb31SNicolin Chen case REG_ASRIDRLC: 606*3117bb31SNicolin Chen case REG_ASR76K: 607*3117bb31SNicolin Chen case REG_ASR56K: 608*3117bb31SNicolin Chen case REG_ASRMCRA: 609*3117bb31SNicolin Chen case REG_ASRFSTA: 610*3117bb31SNicolin Chen case REG_ASRMCRB: 611*3117bb31SNicolin Chen case REG_ASRFSTB: 612*3117bb31SNicolin Chen case REG_ASRMCRC: 613*3117bb31SNicolin Chen case REG_ASRFSTC: 614*3117bb31SNicolin Chen case REG_ASRMCR1A: 615*3117bb31SNicolin Chen case REG_ASRMCR1B: 616*3117bb31SNicolin Chen case REG_ASRMCR1C: 617*3117bb31SNicolin Chen return true; 618*3117bb31SNicolin Chen default: 619*3117bb31SNicolin Chen return false; 620*3117bb31SNicolin Chen } 621*3117bb31SNicolin Chen } 622*3117bb31SNicolin Chen 623*3117bb31SNicolin Chen static bool fsl_asrc_volatile_reg(struct device *dev, unsigned int reg) 624*3117bb31SNicolin Chen { 625*3117bb31SNicolin Chen switch (reg) { 626*3117bb31SNicolin Chen case REG_ASRSTR: 627*3117bb31SNicolin Chen case REG_ASRDIA: 628*3117bb31SNicolin Chen case REG_ASRDIB: 629*3117bb31SNicolin Chen case REG_ASRDIC: 630*3117bb31SNicolin Chen case REG_ASRDOA: 631*3117bb31SNicolin Chen case REG_ASRDOB: 632*3117bb31SNicolin Chen case REG_ASRDOC: 633*3117bb31SNicolin Chen case REG_ASRFSTA: 634*3117bb31SNicolin Chen case REG_ASRFSTB: 635*3117bb31SNicolin Chen case REG_ASRFSTC: 636*3117bb31SNicolin Chen case REG_ASRCFG: 637*3117bb31SNicolin Chen return true; 638*3117bb31SNicolin Chen default: 639*3117bb31SNicolin Chen return false; 640*3117bb31SNicolin Chen } 641*3117bb31SNicolin Chen } 642*3117bb31SNicolin Chen 643*3117bb31SNicolin Chen static bool fsl_asrc_writeable_reg(struct device *dev, unsigned int reg) 644*3117bb31SNicolin Chen { 645*3117bb31SNicolin Chen switch (reg) { 646*3117bb31SNicolin Chen case REG_ASRCTR: 647*3117bb31SNicolin Chen case REG_ASRIER: 648*3117bb31SNicolin Chen case REG_ASRCNCR: 649*3117bb31SNicolin Chen case REG_ASRCFG: 650*3117bb31SNicolin Chen case REG_ASRCSR: 651*3117bb31SNicolin Chen case REG_ASRCDR1: 652*3117bb31SNicolin Chen case REG_ASRCDR2: 653*3117bb31SNicolin Chen case REG_ASRSTR: 654*3117bb31SNicolin Chen case REG_ASRPM1: 655*3117bb31SNicolin Chen case REG_ASRPM2: 656*3117bb31SNicolin Chen case REG_ASRPM3: 657*3117bb31SNicolin Chen case REG_ASRPM4: 658*3117bb31SNicolin Chen case REG_ASRPM5: 659*3117bb31SNicolin Chen case REG_ASRTFR1: 660*3117bb31SNicolin Chen case REG_ASRCCR: 661*3117bb31SNicolin Chen case REG_ASRDIA: 662*3117bb31SNicolin Chen case REG_ASRDIB: 663*3117bb31SNicolin Chen case REG_ASRDIC: 664*3117bb31SNicolin Chen case REG_ASRIDRHA: 665*3117bb31SNicolin Chen case REG_ASRIDRLA: 666*3117bb31SNicolin Chen case REG_ASRIDRHB: 667*3117bb31SNicolin Chen case REG_ASRIDRLB: 668*3117bb31SNicolin Chen case REG_ASRIDRHC: 669*3117bb31SNicolin Chen case REG_ASRIDRLC: 670*3117bb31SNicolin Chen case REG_ASR76K: 671*3117bb31SNicolin Chen case REG_ASR56K: 672*3117bb31SNicolin Chen case REG_ASRMCRA: 673*3117bb31SNicolin Chen case REG_ASRMCRB: 674*3117bb31SNicolin Chen case REG_ASRMCRC: 675*3117bb31SNicolin Chen case REG_ASRMCR1A: 676*3117bb31SNicolin Chen case REG_ASRMCR1B: 677*3117bb31SNicolin Chen case REG_ASRMCR1C: 678*3117bb31SNicolin Chen return true; 679*3117bb31SNicolin Chen default: 680*3117bb31SNicolin Chen return false; 681*3117bb31SNicolin Chen } 682*3117bb31SNicolin Chen } 683*3117bb31SNicolin Chen 684*3117bb31SNicolin Chen static struct regmap_config fsl_asrc_regmap_config = { 685*3117bb31SNicolin Chen .reg_bits = 32, 686*3117bb31SNicolin Chen .reg_stride = 4, 687*3117bb31SNicolin Chen .val_bits = 32, 688*3117bb31SNicolin Chen 689*3117bb31SNicolin Chen .max_register = REG_ASRMCR1C, 690*3117bb31SNicolin Chen .readable_reg = fsl_asrc_readable_reg, 691*3117bb31SNicolin Chen .volatile_reg = fsl_asrc_volatile_reg, 692*3117bb31SNicolin Chen .writeable_reg = fsl_asrc_writeable_reg, 693*3117bb31SNicolin Chen .cache_type = REGCACHE_RBTREE, 694*3117bb31SNicolin Chen }; 695*3117bb31SNicolin Chen 696*3117bb31SNicolin Chen /** 697*3117bb31SNicolin Chen * Initialize ASRC registers with a default configurations 698*3117bb31SNicolin Chen */ 699*3117bb31SNicolin Chen static int fsl_asrc_init(struct fsl_asrc *asrc_priv) 700*3117bb31SNicolin Chen { 701*3117bb31SNicolin Chen /* Halt ASRC internal FP when input FIFO needs data for pair A, B, C */ 702*3117bb31SNicolin Chen regmap_write(asrc_priv->regmap, REG_ASRCTR, ASRCTR_ASRCEN); 703*3117bb31SNicolin Chen 704*3117bb31SNicolin Chen /* Disable interrupt by default */ 705*3117bb31SNicolin Chen regmap_write(asrc_priv->regmap, REG_ASRIER, 0x0); 706*3117bb31SNicolin Chen 707*3117bb31SNicolin Chen /* Apply recommended settings for parameters from Reference Manual */ 708*3117bb31SNicolin Chen regmap_write(asrc_priv->regmap, REG_ASRPM1, 0x7fffff); 709*3117bb31SNicolin Chen regmap_write(asrc_priv->regmap, REG_ASRPM2, 0x255555); 710*3117bb31SNicolin Chen regmap_write(asrc_priv->regmap, REG_ASRPM3, 0xff7280); 711*3117bb31SNicolin Chen regmap_write(asrc_priv->regmap, REG_ASRPM4, 0xff7280); 712*3117bb31SNicolin Chen regmap_write(asrc_priv->regmap, REG_ASRPM5, 0xff7280); 713*3117bb31SNicolin Chen 714*3117bb31SNicolin Chen /* Base address for task queue FIFO. Set to 0x7C */ 715*3117bb31SNicolin Chen regmap_update_bits(asrc_priv->regmap, REG_ASRTFR1, 716*3117bb31SNicolin Chen ASRTFR1_TF_BASE_MASK, ASRTFR1_TF_BASE(0xfc)); 717*3117bb31SNicolin Chen 718*3117bb31SNicolin Chen /* Set the processing clock for 76KHz to 133M */ 719*3117bb31SNicolin Chen regmap_write(asrc_priv->regmap, REG_ASR76K, 0x06D6); 720*3117bb31SNicolin Chen 721*3117bb31SNicolin Chen /* Set the processing clock for 56KHz to 133M */ 722*3117bb31SNicolin Chen return regmap_write(asrc_priv->regmap, REG_ASR56K, 0x0947); 723*3117bb31SNicolin Chen } 724*3117bb31SNicolin Chen 725*3117bb31SNicolin Chen /** 726*3117bb31SNicolin Chen * Interrupt handler for ASRC 727*3117bb31SNicolin Chen */ 728*3117bb31SNicolin Chen static irqreturn_t fsl_asrc_isr(int irq, void *dev_id) 729*3117bb31SNicolin Chen { 730*3117bb31SNicolin Chen struct fsl_asrc *asrc_priv = (struct fsl_asrc *)dev_id; 731*3117bb31SNicolin Chen struct device *dev = &asrc_priv->pdev->dev; 732*3117bb31SNicolin Chen enum asrc_pair_index index; 733*3117bb31SNicolin Chen u32 status; 734*3117bb31SNicolin Chen 735*3117bb31SNicolin Chen regmap_read(asrc_priv->regmap, REG_ASRSTR, &status); 736*3117bb31SNicolin Chen 737*3117bb31SNicolin Chen /* Clean overload error */ 738*3117bb31SNicolin Chen regmap_write(asrc_priv->regmap, REG_ASRSTR, ASRSTR_AOLE); 739*3117bb31SNicolin Chen 740*3117bb31SNicolin Chen /* 741*3117bb31SNicolin Chen * We here use dev_dbg() for all exceptions because ASRC itself does 742*3117bb31SNicolin Chen * not care if FIFO overflowed or underrun while a warning in the 743*3117bb31SNicolin Chen * interrupt would result a ridged conversion. 744*3117bb31SNicolin Chen */ 745*3117bb31SNicolin Chen for (index = ASRC_PAIR_A; index < ASRC_PAIR_MAX_NUM; index++) { 746*3117bb31SNicolin Chen if (!asrc_priv->pair[index]) 747*3117bb31SNicolin Chen continue; 748*3117bb31SNicolin Chen 749*3117bb31SNicolin Chen if (status & ASRSTR_ATQOL) { 750*3117bb31SNicolin Chen asrc_priv->pair[index]->error |= ASRC_TASK_Q_OVERLOAD; 751*3117bb31SNicolin Chen dev_dbg(dev, "ASRC Task Queue FIFO overload\n"); 752*3117bb31SNicolin Chen } 753*3117bb31SNicolin Chen 754*3117bb31SNicolin Chen if (status & ASRSTR_AOOL(index)) { 755*3117bb31SNicolin Chen asrc_priv->pair[index]->error |= ASRC_OUTPUT_TASK_OVERLOAD; 756*3117bb31SNicolin Chen pair_dbg("Output Task Overload\n"); 757*3117bb31SNicolin Chen } 758*3117bb31SNicolin Chen 759*3117bb31SNicolin Chen if (status & ASRSTR_AIOL(index)) { 760*3117bb31SNicolin Chen asrc_priv->pair[index]->error |= ASRC_INPUT_TASK_OVERLOAD; 761*3117bb31SNicolin Chen pair_dbg("Input Task Overload\n"); 762*3117bb31SNicolin Chen } 763*3117bb31SNicolin Chen 764*3117bb31SNicolin Chen if (status & ASRSTR_AODO(index)) { 765*3117bb31SNicolin Chen asrc_priv->pair[index]->error |= ASRC_OUTPUT_BUFFER_OVERFLOW; 766*3117bb31SNicolin Chen pair_dbg("Output Data Buffer has overflowed\n"); 767*3117bb31SNicolin Chen } 768*3117bb31SNicolin Chen 769*3117bb31SNicolin Chen if (status & ASRSTR_AIDU(index)) { 770*3117bb31SNicolin Chen asrc_priv->pair[index]->error |= ASRC_INPUT_BUFFER_UNDERRUN; 771*3117bb31SNicolin Chen pair_dbg("Input Data Buffer has underflowed\n"); 772*3117bb31SNicolin Chen } 773*3117bb31SNicolin Chen } 774*3117bb31SNicolin Chen 775*3117bb31SNicolin Chen return IRQ_HANDLED; 776*3117bb31SNicolin Chen } 777*3117bb31SNicolin Chen 778*3117bb31SNicolin Chen static int fsl_asrc_probe(struct platform_device *pdev) 779*3117bb31SNicolin Chen { 780*3117bb31SNicolin Chen struct device_node *np = pdev->dev.of_node; 781*3117bb31SNicolin Chen struct fsl_asrc *asrc_priv; 782*3117bb31SNicolin Chen struct resource *res; 783*3117bb31SNicolin Chen void __iomem *regs; 784*3117bb31SNicolin Chen int irq, ret, i; 785*3117bb31SNicolin Chen char tmp[16]; 786*3117bb31SNicolin Chen 787*3117bb31SNicolin Chen asrc_priv = devm_kzalloc(&pdev->dev, sizeof(*asrc_priv), GFP_KERNEL); 788*3117bb31SNicolin Chen if (!asrc_priv) 789*3117bb31SNicolin Chen return -ENOMEM; 790*3117bb31SNicolin Chen 791*3117bb31SNicolin Chen asrc_priv->pdev = pdev; 792*3117bb31SNicolin Chen strcpy(asrc_priv->name, np->name); 793*3117bb31SNicolin Chen 794*3117bb31SNicolin Chen /* Get the addresses and IRQ */ 795*3117bb31SNicolin Chen res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 796*3117bb31SNicolin Chen regs = devm_ioremap_resource(&pdev->dev, res); 797*3117bb31SNicolin Chen if (IS_ERR(regs)) 798*3117bb31SNicolin Chen return PTR_ERR(regs); 799*3117bb31SNicolin Chen 800*3117bb31SNicolin Chen asrc_priv->paddr = res->start; 801*3117bb31SNicolin Chen 802*3117bb31SNicolin Chen /* Register regmap and let it prepare core clock */ 803*3117bb31SNicolin Chen if (of_property_read_bool(np, "big-endian")) 804*3117bb31SNicolin Chen fsl_asrc_regmap_config.val_format_endian = REGMAP_ENDIAN_BIG; 805*3117bb31SNicolin Chen 806*3117bb31SNicolin Chen asrc_priv->regmap = devm_regmap_init_mmio_clk(&pdev->dev, "mem", regs, 807*3117bb31SNicolin Chen &fsl_asrc_regmap_config); 808*3117bb31SNicolin Chen if (IS_ERR(asrc_priv->regmap)) { 809*3117bb31SNicolin Chen dev_err(&pdev->dev, "failed to init regmap\n"); 810*3117bb31SNicolin Chen return PTR_ERR(asrc_priv->regmap); 811*3117bb31SNicolin Chen } 812*3117bb31SNicolin Chen 813*3117bb31SNicolin Chen irq = platform_get_irq(pdev, 0); 814*3117bb31SNicolin Chen if (irq < 0) { 815*3117bb31SNicolin Chen dev_err(&pdev->dev, "no irq for node %s\n", np->full_name); 816*3117bb31SNicolin Chen return irq; 817*3117bb31SNicolin Chen } 818*3117bb31SNicolin Chen 819*3117bb31SNicolin Chen ret = devm_request_irq(&pdev->dev, irq, fsl_asrc_isr, 0, 820*3117bb31SNicolin Chen asrc_priv->name, asrc_priv); 821*3117bb31SNicolin Chen if (ret) { 822*3117bb31SNicolin Chen dev_err(&pdev->dev, "failed to claim irq %u: %d\n", irq, ret); 823*3117bb31SNicolin Chen return ret; 824*3117bb31SNicolin Chen } 825*3117bb31SNicolin Chen 826*3117bb31SNicolin Chen asrc_priv->mem_clk = devm_clk_get(&pdev->dev, "mem"); 827*3117bb31SNicolin Chen if (IS_ERR(asrc_priv->mem_clk)) { 828*3117bb31SNicolin Chen dev_err(&pdev->dev, "failed to get mem clock\n"); 829*3117bb31SNicolin Chen return PTR_ERR(asrc_priv->ipg_clk); 830*3117bb31SNicolin Chen } 831*3117bb31SNicolin Chen 832*3117bb31SNicolin Chen asrc_priv->ipg_clk = devm_clk_get(&pdev->dev, "ipg"); 833*3117bb31SNicolin Chen if (IS_ERR(asrc_priv->ipg_clk)) { 834*3117bb31SNicolin Chen dev_err(&pdev->dev, "failed to get ipg clock\n"); 835*3117bb31SNicolin Chen return PTR_ERR(asrc_priv->ipg_clk); 836*3117bb31SNicolin Chen } 837*3117bb31SNicolin Chen 838*3117bb31SNicolin Chen for (i = 0; i < ASRC_CLK_MAX_NUM; i++) { 839*3117bb31SNicolin Chen sprintf(tmp, "asrck_%x", i); 840*3117bb31SNicolin Chen asrc_priv->asrck_clk[i] = devm_clk_get(&pdev->dev, tmp); 841*3117bb31SNicolin Chen if (IS_ERR(asrc_priv->asrck_clk[i])) { 842*3117bb31SNicolin Chen dev_err(&pdev->dev, "failed to get %s clock\n", tmp); 843*3117bb31SNicolin Chen return PTR_ERR(asrc_priv->asrck_clk[i]); 844*3117bb31SNicolin Chen } 845*3117bb31SNicolin Chen } 846*3117bb31SNicolin Chen 847*3117bb31SNicolin Chen if (of_device_is_compatible(pdev->dev.of_node, "fsl,imx35-asrc")) { 848*3117bb31SNicolin Chen asrc_priv->channel_bits = 3; 849*3117bb31SNicolin Chen clk_map[IN] = input_clk_map_imx35; 850*3117bb31SNicolin Chen clk_map[OUT] = output_clk_map_imx35; 851*3117bb31SNicolin Chen } else { 852*3117bb31SNicolin Chen asrc_priv->channel_bits = 4; 853*3117bb31SNicolin Chen clk_map[IN] = input_clk_map_imx53; 854*3117bb31SNicolin Chen clk_map[OUT] = output_clk_map_imx53; 855*3117bb31SNicolin Chen } 856*3117bb31SNicolin Chen 857*3117bb31SNicolin Chen ret = fsl_asrc_init(asrc_priv); 858*3117bb31SNicolin Chen if (ret) { 859*3117bb31SNicolin Chen dev_err(&pdev->dev, "failed to init asrc %d\n", ret); 860*3117bb31SNicolin Chen return -EINVAL; 861*3117bb31SNicolin Chen } 862*3117bb31SNicolin Chen 863*3117bb31SNicolin Chen asrc_priv->channel_avail = 10; 864*3117bb31SNicolin Chen 865*3117bb31SNicolin Chen ret = of_property_read_u32(np, "fsl,asrc-rate", 866*3117bb31SNicolin Chen &asrc_priv->asrc_rate); 867*3117bb31SNicolin Chen if (ret) { 868*3117bb31SNicolin Chen dev_err(&pdev->dev, "failed to get output rate\n"); 869*3117bb31SNicolin Chen return -EINVAL; 870*3117bb31SNicolin Chen } 871*3117bb31SNicolin Chen 872*3117bb31SNicolin Chen ret = of_property_read_u32(np, "fsl,asrc-width", 873*3117bb31SNicolin Chen &asrc_priv->asrc_width); 874*3117bb31SNicolin Chen if (ret) { 875*3117bb31SNicolin Chen dev_err(&pdev->dev, "failed to get output width\n"); 876*3117bb31SNicolin Chen return -EINVAL; 877*3117bb31SNicolin Chen } 878*3117bb31SNicolin Chen 879*3117bb31SNicolin Chen if (asrc_priv->asrc_width != 16 && asrc_priv->asrc_width != 24) { 880*3117bb31SNicolin Chen dev_warn(&pdev->dev, "unsupported width, switching to 24bit\n"); 881*3117bb31SNicolin Chen asrc_priv->asrc_width = 24; 882*3117bb31SNicolin Chen } 883*3117bb31SNicolin Chen 884*3117bb31SNicolin Chen platform_set_drvdata(pdev, asrc_priv); 885*3117bb31SNicolin Chen pm_runtime_enable(&pdev->dev); 886*3117bb31SNicolin Chen spin_lock_init(&asrc_priv->lock); 887*3117bb31SNicolin Chen 888*3117bb31SNicolin Chen ret = devm_snd_soc_register_component(&pdev->dev, &fsl_asrc_component, 889*3117bb31SNicolin Chen &fsl_asrc_dai, 1); 890*3117bb31SNicolin Chen if (ret) { 891*3117bb31SNicolin Chen dev_err(&pdev->dev, "failed to register ASoC DAI\n"); 892*3117bb31SNicolin Chen return ret; 893*3117bb31SNicolin Chen } 894*3117bb31SNicolin Chen 895*3117bb31SNicolin Chen ret = devm_snd_soc_register_platform(&pdev->dev, &fsl_asrc_platform); 896*3117bb31SNicolin Chen if (ret) { 897*3117bb31SNicolin Chen dev_err(&pdev->dev, "failed to register ASoC platform\n"); 898*3117bb31SNicolin Chen return ret; 899*3117bb31SNicolin Chen } 900*3117bb31SNicolin Chen 901*3117bb31SNicolin Chen dev_info(&pdev->dev, "driver registered\n"); 902*3117bb31SNicolin Chen 903*3117bb31SNicolin Chen return 0; 904*3117bb31SNicolin Chen } 905*3117bb31SNicolin Chen 906*3117bb31SNicolin Chen #if CONFIG_PM_RUNTIME 907*3117bb31SNicolin Chen static int fsl_asrc_runtime_resume(struct device *dev) 908*3117bb31SNicolin Chen { 909*3117bb31SNicolin Chen struct fsl_asrc *asrc_priv = dev_get_drvdata(dev); 910*3117bb31SNicolin Chen int i; 911*3117bb31SNicolin Chen 912*3117bb31SNicolin Chen clk_prepare_enable(asrc_priv->mem_clk); 913*3117bb31SNicolin Chen clk_prepare_enable(asrc_priv->ipg_clk); 914*3117bb31SNicolin Chen for (i = 0; i < ASRC_CLK_MAX_NUM; i++) 915*3117bb31SNicolin Chen clk_prepare_enable(asrc_priv->asrck_clk[i]); 916*3117bb31SNicolin Chen 917*3117bb31SNicolin Chen return 0; 918*3117bb31SNicolin Chen } 919*3117bb31SNicolin Chen 920*3117bb31SNicolin Chen static int fsl_asrc_runtime_suspend(struct device *dev) 921*3117bb31SNicolin Chen { 922*3117bb31SNicolin Chen struct fsl_asrc *asrc_priv = dev_get_drvdata(dev); 923*3117bb31SNicolin Chen int i; 924*3117bb31SNicolin Chen 925*3117bb31SNicolin Chen for (i = 0; i < ASRC_CLK_MAX_NUM; i++) 926*3117bb31SNicolin Chen clk_disable_unprepare(asrc_priv->asrck_clk[i]); 927*3117bb31SNicolin Chen clk_disable_unprepare(asrc_priv->ipg_clk); 928*3117bb31SNicolin Chen clk_disable_unprepare(asrc_priv->mem_clk); 929*3117bb31SNicolin Chen 930*3117bb31SNicolin Chen return 0; 931*3117bb31SNicolin Chen } 932*3117bb31SNicolin Chen #endif /* CONFIG_PM_RUNTIME */ 933*3117bb31SNicolin Chen 934*3117bb31SNicolin Chen #if CONFIG_PM_SLEEP 935*3117bb31SNicolin Chen static int fsl_asrc_suspend(struct device *dev) 936*3117bb31SNicolin Chen { 937*3117bb31SNicolin Chen struct fsl_asrc *asrc_priv = dev_get_drvdata(dev); 938*3117bb31SNicolin Chen 939*3117bb31SNicolin Chen regcache_cache_only(asrc_priv->regmap, true); 940*3117bb31SNicolin Chen regcache_mark_dirty(asrc_priv->regmap); 941*3117bb31SNicolin Chen 942*3117bb31SNicolin Chen return 0; 943*3117bb31SNicolin Chen } 944*3117bb31SNicolin Chen 945*3117bb31SNicolin Chen static int fsl_asrc_resume(struct device *dev) 946*3117bb31SNicolin Chen { 947*3117bb31SNicolin Chen struct fsl_asrc *asrc_priv = dev_get_drvdata(dev); 948*3117bb31SNicolin Chen u32 asrctr; 949*3117bb31SNicolin Chen 950*3117bb31SNicolin Chen /* Stop all pairs provisionally */ 951*3117bb31SNicolin Chen regmap_read(asrc_priv->regmap, REG_ASRCTR, &asrctr); 952*3117bb31SNicolin Chen regmap_update_bits(asrc_priv->regmap, REG_ASRCTR, 953*3117bb31SNicolin Chen ASRCTR_ASRCEi_ALL_MASK, 0); 954*3117bb31SNicolin Chen 955*3117bb31SNicolin Chen /* Restore all registers */ 956*3117bb31SNicolin Chen regcache_cache_only(asrc_priv->regmap, false); 957*3117bb31SNicolin Chen regcache_sync(asrc_priv->regmap); 958*3117bb31SNicolin Chen 959*3117bb31SNicolin Chen /* Restart enabled pairs */ 960*3117bb31SNicolin Chen regmap_update_bits(asrc_priv->regmap, REG_ASRCTR, 961*3117bb31SNicolin Chen ASRCTR_ASRCEi_ALL_MASK, asrctr); 962*3117bb31SNicolin Chen 963*3117bb31SNicolin Chen return 0; 964*3117bb31SNicolin Chen } 965*3117bb31SNicolin Chen #endif /* CONFIG_PM_SLEEP */ 966*3117bb31SNicolin Chen 967*3117bb31SNicolin Chen static const struct dev_pm_ops fsl_asrc_pm = { 968*3117bb31SNicolin Chen SET_RUNTIME_PM_OPS(fsl_asrc_runtime_suspend, fsl_asrc_runtime_resume, NULL) 969*3117bb31SNicolin Chen SET_SYSTEM_SLEEP_PM_OPS(fsl_asrc_suspend, fsl_asrc_resume) 970*3117bb31SNicolin Chen }; 971*3117bb31SNicolin Chen 972*3117bb31SNicolin Chen static const struct of_device_id fsl_asrc_ids[] = { 973*3117bb31SNicolin Chen { .compatible = "fsl,imx35-asrc", }, 974*3117bb31SNicolin Chen { .compatible = "fsl,imx53-asrc", }, 975*3117bb31SNicolin Chen {} 976*3117bb31SNicolin Chen }; 977*3117bb31SNicolin Chen MODULE_DEVICE_TABLE(of, fsl_asrc_ids); 978*3117bb31SNicolin Chen 979*3117bb31SNicolin Chen static struct platform_driver fsl_asrc_driver = { 980*3117bb31SNicolin Chen .probe = fsl_asrc_probe, 981*3117bb31SNicolin Chen .driver = { 982*3117bb31SNicolin Chen .name = "fsl-asrc", 983*3117bb31SNicolin Chen .of_match_table = fsl_asrc_ids, 984*3117bb31SNicolin Chen .pm = &fsl_asrc_pm, 985*3117bb31SNicolin Chen }, 986*3117bb31SNicolin Chen }; 987*3117bb31SNicolin Chen module_platform_driver(fsl_asrc_driver); 988*3117bb31SNicolin Chen 989*3117bb31SNicolin Chen MODULE_DESCRIPTION("Freescale ASRC ASoC driver"); 990*3117bb31SNicolin Chen MODULE_AUTHOR("Nicolin Chen <nicoleotsuka@gmail.com>"); 991*3117bb31SNicolin Chen MODULE_ALIAS("platform:fsl-asrc"); 992*3117bb31SNicolin Chen MODULE_LICENSE("GPL v2"); 993