/* * settting function */ u32 rsnd_get_adinr(struct rsnd_mod *mod) { struct rsnd_priv *priv = rsnd_mod_to_priv(mod); struct rsnd_dai_stream *io = rsnd_mod_to_io(mod); struct snd_pcm_runtime *runtime = rsnd_io_to_runtime(io); struct device *dev = rsnd_priv_to_dev(priv); u32 adinr = runtime->channels; switch (runtime->sample_bits) { case 16: adinr |= (8 << 16); break; case 32: adinr |= (0 << 16); break; default: dev_warn(dev, "not supported sample bits\n"); return 0; } return adinr; }
static int rsnd_src_set_convert_rate(struct rsnd_mod *mod, struct rsnd_dai *rdai) { struct rsnd_dai_stream *io = rsnd_mod_to_io(mod); struct snd_pcm_runtime *runtime = rsnd_io_to_runtime(io); struct rsnd_src *src = rsnd_mod_to_src(mod); u32 convert_rate = rsnd_src_convert_rate(src); u32 fsrate = 0; if (convert_rate) fsrate = 0x0400000 / convert_rate * runtime->rate; /* set/clear soft reset */ rsnd_mod_write(mod, SRC_SWRSR, 0); rsnd_mod_write(mod, SRC_SWRSR, 1); /* * Initialize the operation of the SRC internal circuits * see rsnd_src_start() */ rsnd_mod_write(mod, SRC_SRCIR, 1); /* Set channel number and output bit length */ rsnd_mod_write(mod, SRC_ADINR, rsnd_get_adinr(mod)); /* Enable the initial value of IFS */ if (fsrate) { rsnd_mod_write(mod, SRC_IFSCR, 1); /* Set initial value of IFS */ rsnd_mod_write(mod, SRC_IFSVR, fsrate); } /* use DMA transfer */ rsnd_mod_write(mod, SRC_BUSIF_MODE, 1); return 0; }
/* * Gen1 functions */ static int rsnd_src_set_route_gen1(struct rsnd_mod *mod, struct rsnd_dai *rdai) { struct rsnd_dai_stream *io = rsnd_mod_to_io(mod); struct src_route_config { u32 mask; int shift; } routes[] = { { 0xF, 0, }, /* 0 */ { 0xF, 4, }, /* 1 */ { 0xF, 8, }, /* 2 */ { 0x7, 12, }, /* 3 */ { 0x7, 16, }, /* 4 */ { 0x7, 20, }, /* 5 */ { 0x7, 24, }, /* 6 */ { 0x3, 28, }, /* 7 */ { 0x3, 30, }, /* 8 */ }; u32 mask; u32 val; int id; id = rsnd_mod_id(mod); if (id < 0 || id >= ARRAY_SIZE(routes)) return -EIO; /* * SRC_ROUTE_SELECT */ val = rsnd_dai_is_play(rdai, io) ? 0x1 : 0x2; val = val << routes[id].shift; mask = routes[id].mask << routes[id].shift; rsnd_mod_bset(mod, SRC_ROUTE_SEL, mask, val); return 0; }
/* * Gen1/Gen2 common functions */ int rsnd_src_ssiu_start(struct rsnd_mod *ssi_mod, int use_busif) { struct rsnd_dai_stream *io = rsnd_mod_to_io(ssi_mod); struct rsnd_dai *rdai = rsnd_io_to_rdai(io); struct snd_pcm_runtime *runtime = rsnd_io_to_runtime(io); int ssi_id = rsnd_mod_id(ssi_mod); /* * SSI_MODE0 */ rsnd_mod_bset(ssi_mod, SSI_MODE0, (1 << ssi_id), !use_busif << ssi_id); /* * SSI_MODE1 */ if (rsnd_ssi_is_pin_sharing(ssi_mod)) { int shift = -1; switch (ssi_id) { case 1: shift = 0; break; case 2: shift = 2; break; case 4: shift = 16; break; } if (shift >= 0) rsnd_mod_bset(ssi_mod, SSI_MODE1, 0x3 << shift, rsnd_rdai_is_clk_master(rdai) ? 0x2 << shift : 0x1 << shift); } /* * DMA settings for SSIU */ if (use_busif) { u32 val = 0x76543210; u32 mask = ~0; rsnd_mod_write(ssi_mod, SSI_BUSIF_ADINR, rsnd_get_adinr(ssi_mod)); rsnd_mod_write(ssi_mod, SSI_BUSIF_MODE, 1); rsnd_mod_write(ssi_mod, SSI_CTRL, 0x1); mask <<= runtime->channels * 4; val = val & mask; switch (runtime->sample_bits) { case 16: val |= 0x67452301 & ~mask; break; case 32: val |= 0x76543210 & ~mask; break; } rsnd_mod_write(ssi_mod, BUSIF_DALIGN, val); } return 0; }