* [PATCH v2] ASoC: amd: acp: Add TDM support for acp i2s stream
@ 2022-08-05 6:04 Venkata Prasad Potturu
[not found] ` <202208071454.7YeHuTDb-lkp@intel.com>
0 siblings, 1 reply; 2+ messages in thread
From: Venkata Prasad Potturu @ 2022-08-05 6:04 UTC (permalink / raw)
To: broonie, alsa-devel
Cc: Sunil-kumar.Dommati, ssabakar, Ajit Kumar Pandey,
Venkata Prasad Potturu, open list, Basavaraj.Hiregoudar,
Takashi Iwai, Liam Girdwood, Vijendar.Mukunda,
V sujith kumar Reddy
Add callback and code changes to enable ACP I2S controller in TDM
mode. Add new fields in acp_stream and acp_dev_data struct to configure
tdm related registers for ACP i2s controllers.
Signed-off-by: Venkata Prasad Potturu <venkataprasad.potturu@amd.com>
---
Depends on:-
-- https://patchwork.kernel.org/project/alsa-devel/patch/20220804072556.601396-1-venkataprasad.potturu@amd.com/
-- https://patchwork.kernel.org/project/alsa-devel/patch/20220801063501.51439-1-venkataprasad.potturu@amd.com/
Changes since v1:
-- Add spin lock where linked list is referring.
sound/soc/amd/acp/acp-i2s.c | 80 ++++++++++++++++++++++++++++++++++++-
sound/soc/amd/acp/amd.h | 12 ++++++
2 files changed, 91 insertions(+), 1 deletion(-)
diff --git a/sound/soc/amd/acp/acp-i2s.c b/sound/soc/amd/acp/acp-i2s.c
index 393f729ef561..ac416572db0d 100644
--- a/sound/soc/amd/acp/acp-i2s.c
+++ b/sound/soc/amd/acp/acp-i2s.c
@@ -25,6 +25,65 @@
#define DRV_NAME "acp_i2s_playcap"
+static int acp_i2s_set_fmt(struct snd_soc_dai *cpu_dai,
+ unsigned int fmt)
+{
+ struct acp_dev_data *adata = snd_soc_dai_get_drvdata(cpu_dai);
+ int mode;
+
+ mode = fmt & SND_SOC_DAIFMT_FORMAT_MASK;
+ switch (mode) {
+ case SND_SOC_DAIFMT_I2S:
+ adata->tdm_mode = TDM_DISABLE;
+ break;
+ case SND_SOC_DAIFMT_DSP_A:
+ adata->tdm_mode = TDM_ENABLE;
+ break;
+ default:
+ return -EINVAL;
+ }
+ return 0;
+}
+
+static int acp_i2s_set_tdm_slot(struct snd_soc_dai *dai, u32 tx_mask, u32 rx_mask,
+ int slots, int slot_width)
+{
+ struct device *dev = dai->component->dev;
+ struct acp_dev_data *adata = snd_soc_dai_get_drvdata(dai);
+ struct acp_stream *stream;
+ int slot_len;
+
+ switch (slot_width) {
+ case SLOT_WIDTH_8:
+ slot_len = 8;
+ break;
+ case SLOT_WIDTH_16:
+ slot_len = 16;
+ break;
+ case SLOT_WIDTH_24:
+ slot_len = 24;
+ break;
+ case SLOT_WIDTH_32:
+ slot_len = 0;
+ break;
+ default:
+ dev_err(dev, "Unsupported bitdepth %d\n", slot_width);
+ return -EINVAL;
+ }
+
+ spin_lock_irq(&adata->acp_lock);
+ list_for_each_entry(stream, &adata->stream_list, list) {
+ if (tx_mask && stream->dir == SNDRV_PCM_STREAM_PLAYBACK)
+ adata->tdm_tx_fmt[stream->dai_id - 1] =
+ FRM_LEN | (slots << 15) | (slot_len << 18);
+ else if (rx_mask && stream->dir == SNDRV_PCM_STREAM_CAPTURE)
+ adata->tdm_rx_fmt[stream->dai_id - 1] =
+ FRM_LEN | (slots << 15) | (slot_len << 18);
+ }
+ spin_unlock_irq(&adata->acp_lock);
+ return 0;
+}
+
static int acp_i2s_hwparams(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params,
struct snd_soc_dai *dai)
{
@@ -33,7 +92,7 @@ static int acp_i2s_hwparams(struct snd_pcm_substream *substream, struct snd_pcm_
struct acp_resource *rsrc;
u32 val;
u32 xfer_resolution;
- u32 reg_val;
+ u32 reg_val, fmt_reg, tdm_fmt;
u32 lrclk_div_val, bclk_div_val;
adata = snd_soc_dai_get_drvdata(dai);
@@ -62,12 +121,15 @@ static int acp_i2s_hwparams(struct snd_pcm_substream *substream, struct snd_pcm_
switch (dai->driver->id) {
case I2S_BT_INSTANCE:
reg_val = ACP_BTTDM_ITER;
+ fmt_reg = ACP_BTTDM_TXFRMT;
break;
case I2S_SP_INSTANCE:
reg_val = ACP_I2STDM_ITER;
+ fmt_reg = ACP_I2STDM_TXFRMT;
break;
case I2S_HS_INSTANCE:
reg_val = ACP_HSTDM_ITER;
+ fmt_reg = ACP_HSTDM_TXFRMT;
break;
default:
dev_err(dev, "Invalid dai id %x\n", dai->driver->id);
@@ -77,12 +139,15 @@ static int acp_i2s_hwparams(struct snd_pcm_substream *substream, struct snd_pcm_
switch (dai->driver->id) {
case I2S_BT_INSTANCE:
reg_val = ACP_BTTDM_IRER;
+ fmt_reg = ACP_BTTDM_RXFRMT;
break;
case I2S_SP_INSTANCE:
reg_val = ACP_I2STDM_IRER;
+ fmt_reg = ACP_I2STDM_RXFRMT;
break;
case I2S_HS_INSTANCE:
reg_val = ACP_HSTDM_IRER;
+ fmt_reg = ACP_HSTDM_RXFRMT;
break;
default:
dev_err(dev, "Invalid dai id %x\n", dai->driver->id);
@@ -95,6 +160,16 @@ static int acp_i2s_hwparams(struct snd_pcm_substream *substream, struct snd_pcm_
val = val | (xfer_resolution << 3);
writel(val, adata->acp_base + reg_val);
+ if (adata->tdm_mode) {
+ val = readl(adata->acp_base + reg_val);
+ writel(val | BIT(1), adata->acp_base + reg_val);
+ if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
+ tdm_fmt = adata->tdm_tx_fmt[dai->driver->id - 1];
+ else
+ tdm_fmt = adata->tdm_rx_fmt[dai->driver->id - 1];
+ writel(tdm_fmt, adata->acp_base + fmt_reg);
+ }
+
if (rsrc->soc_mclk) {
switch (params_format(params)) {
case SNDRV_PCM_FORMAT_S16_LE:
@@ -443,6 +518,7 @@ static int acp_i2s_startup(struct snd_pcm_substream *substream, struct snd_soc_d
stream->id = dai->driver->id + dir;
stream->dai_id = dai->driver->id;
stream->irq_bit = irq_bit;
+ stream->dir = substream->stream;
return 0;
}
@@ -452,6 +528,8 @@ const struct snd_soc_dai_ops asoc_acp_cpu_dai_ops = {
.hw_params = acp_i2s_hwparams,
.prepare = acp_i2s_prepare,
.trigger = acp_i2s_trigger,
+ .set_fmt = acp_i2s_set_fmt,
+ .set_tdm_slot = acp_i2s_set_tdm_slot,
};
EXPORT_SYMBOL_NS_GPL(asoc_acp_cpu_dai_ops, SND_SOC_ACP_COMMON);
diff --git a/sound/soc/amd/acp/amd.h b/sound/soc/amd/acp/amd.h
index be8bb8247c4e..5f2119f42271 100644
--- a/sound/soc/amd/acp/amd.h
+++ b/sound/soc/amd/acp/amd.h
@@ -84,6 +84,14 @@
#define ACP_MAX_STREAM 8
+#define TDM_ENABLE 1
+#define TDM_DISABLE 0
+
+#define SLOT_WIDTH_8 0x8
+#define SLOT_WIDTH_16 0x10
+#define SLOT_WIDTH_24 0x18
+#define SLOT_WIDTH_32 0x20
+
struct acp_chip_info {
char *name; /* Platform name */
unsigned int acp_rev; /* ACP Revision id */
@@ -96,6 +104,7 @@ struct acp_stream {
int irq_bit;
int dai_id;
int id;
+ int dir;
u64 bytescount;
u32 reg_offset;
u32 pte_offset;
@@ -120,6 +129,7 @@ struct acp_dev_data {
void __iomem *acp_base;
unsigned int i2s_irq;
+ bool tdm_mode;
/* SOC specific dais */
struct snd_soc_dai_driver *dai_driver;
int num_dai;
@@ -134,6 +144,8 @@ struct acp_dev_data {
u32 lrclk_div;
struct acp_resource *rsrc;
+ u32 tdm_tx_fmt[3];
+ u32 tdm_rx_fmt[3];
};
union acp_i2stdm_mstrclkgen {
--
2.25.1
^ permalink raw reply related [flat|nested] 2+ messages in thread
* Re: [PATCH v2] ASoC: amd: acp: Add TDM support for acp i2s stream
[not found] ` <202208071454.7YeHuTDb-lkp@intel.com>
@ 2022-08-10 13:15 ` Venkata Prasad Potturu
0 siblings, 0 replies; 2+ messages in thread
From: Venkata Prasad Potturu @ 2022-08-10 13:15 UTC (permalink / raw)
To: kernel test robot, broonie, alsa-devel
Cc: Sunil-kumar.Dommati, kbuild-all, ssabakar, open list,
Basavaraj.Hiregoudar, Takashi Iwai, Liam Girdwood,
Vijendar.Mukunda, vsujithkumar.reddy
On 8/7/22 12:35, kernel test robot wrote:
> Hi Venkata,
>
> Thank you for the patch! Yet something to improve:
>
> [auto build test ERROR on broonie-sound/for-next]
> [also build test ERROR on linus/master next-20220805]
> [cannot apply to v5.19]
> [If your patch is applied to the wrong git tree, kindly drop us a note.
> And when submitting patch, we suggest to use '--base' as documented in
> https://nam11.safelinks.protection.outlook.com/?url=https%3A%2F%2Fgit-scm.com%2Fdocs%2Fgit-format-patch%23_base_tree_information&data=05%7C01%7Cvenkataprasad.potturu%40amd.com%7C06397243ad964e430c5a08da784359bd%7C3dd8961fe4884e608e11a82d994e183d%7C0%7C0%7C637954527920715155%7CUnknown%7CTWFpbGZsb3d8eyJWIjoiMC4wLjAwMDAiLCJQIjoiV2luMzIiLCJBTiI6Ik1haWwiLCJXVCI6Mn0%3D%7C3000%7C%7C%7C&sdata=OorbaHKuOoqW7DbCbwTtKSOrN3WRBFmaIO7Ua5S2Ag4%3D&reserved=0]
>
> url:https://nam11.safelinks.protection.outlook.com/?url=https%3A%2F%2Fgithub.com%2Fintel-lab-lkp%2Flinux%2Fcommits%2FVenkata-Prasad-Potturu%2FASoC-amd-acp-Add-TDM-support-for-acp-i2s-stream%2F20220805-140248&data=05%7C01%7Cvenkataprasad.potturu%40amd.com%7C06397243ad964e430c5a08da784359bd%7C3dd8961fe4884e608e11a82d994e183d%7C0%7C0%7C637954527920715155%7CUnknown%7CTWFpbGZsb3d8eyJWIjoiMC4wLjAwMDAiLCJQIjoiV2luMzIiLCJBTiI6Ik1haWwiLCJXVCI6Mn0%3D%7C3000%7C%7C%7C&sdata=%2FcL1tCMcR1Rp21LLla2hS18EjziPLIOZC7GSPaRMkyE%3D&reserved=0
> base:https://nam11.safelinks.protection.outlook.com/?url=https%3A%2F%2Fgit.kernel.org%2Fpub%2Fscm%2Flinux%2Fkernel%2Fgit%2Fbroonie%2Fsound.git&data=05%7C01%7Cvenkataprasad.potturu%40amd.com%7C06397243ad964e430c5a08da784359bd%7C3dd8961fe4884e608e11a82d994e183d%7C0%7C0%7C637954527920715155%7CUnknown%7CTWFpbGZsb3d8eyJWIjoiMC4wLjAwMDAiLCJQIjoiV2luMzIiLCJBTiI6Ik1haWwiLCJXVCI6Mn0%3D%7C3000%7C%7C%7C&sdata=SnIKf3DpfeNAJWTtvykRyEGfn7sRyiuvmK3eA5vr3qk%3D&reserved=0 for-next
> config: x86_64-allmodconfig (https://nam11.safelinks.protection.outlook.com/?url=https%3A%2F%2Fdownload.01.org%2F0day-ci%2Farchive%2F20220807%2F202208071454.7YeHuTDb-lkp%40intel.com%2Fconfig&data=05%7C01%7Cvenkataprasad.potturu%40amd.com%7C06397243ad964e430c5a08da784359bd%7C3dd8961fe4884e608e11a82d994e183d%7C0%7C0%7C637954527920715155%7CUnknown%7CTWFpbGZsb3d8eyJWIjoiMC4wLjAwMDAiLCJQIjoiV2luMzIiLCJBTiI6Ik1haWwiLCJXVCI6Mn0%3D%7C3000%7C%7C%7C&sdata=3kQqmQcSpeZBiCUjR%2FesvNOECdVFNS3olWv6IGfdy04%3D&reserved=0)
> compiler: gcc-11 (Debian 11.3.0-3) 11.3.0
> reproduce (this is a W=1 build):
> #https://nam11.safelinks.protection.outlook.com/?url=https%3A%2F%2Fgithub.com%2Fintel-lab-lkp%2Flinux%2Fcommit%2Fc603f9570621784501d7ce7f5099be37983cb810&data=05%7C01%7Cvenkataprasad.potturu%40amd.com%7C06397243ad964e430c5a08da784359bd%7C3dd8961fe4884e608e11a82d994e183d%7C0%7C0%7C637954527920715155%7CUnknown%7CTWFpbGZsb3d8eyJWIjoiMC4wLjAwMDAiLCJQIjoiV2luMzIiLCJBTiI6Ik1haWwiLCJXVCI6Mn0%3D%7C3000%7C%7C%7C&sdata=QaOUzq7KDkNDmDtTbawTnpB46weD9fXj8rnZmxUC9kI%3D&reserved=0
> git remote add linux-reviewhttps://nam11.safelinks.protection.outlook.com/?url=https%3A%2F%2Fgithub.com%2Fintel-lab-lkp%2Flinux&data=05%7C01%7Cvenkataprasad.potturu%40amd.com%7C06397243ad964e430c5a08da784359bd%7C3dd8961fe4884e608e11a82d994e183d%7C0%7C0%7C637954527920715155%7CUnknown%7CTWFpbGZsb3d8eyJWIjoiMC4wLjAwMDAiLCJQIjoiV2luMzIiLCJBTiI6Ik1haWwiLCJXVCI6Mn0%3D%7C3000%7C%7C%7C&sdata=gLAIdogl48m5fKI5Sz5sUuU9faIl32G%2BZTKAs183tBk%3D&reserved=0
> git fetch --no-tags linux-review Venkata-Prasad-Potturu/ASoC-amd-acp-Add-TDM-support-for-acp-i2s-stream/20220805-140248
> git checkout c603f9570621784501d7ce7f5099be37983cb810
> # save the config file
> mkdir build_dir && cp config build_dir/.config
> make W=1 O=build_dir ARCH=x86_64 SHELL=/bin/bash sound/soc/
>
> If you fix the issue, kindly add following tag where applicable
> Reported-by: kernel test robot<lkp@intel.com>
>
> All errors (new ones prefixed by >>):
>
> sound/soc/amd/acp/acp-i2s.c: In function 'acp_i2s_set_tdm_slot':
>>> sound/soc/amd/acp/acp-i2s.c:74:29: error: 'struct acp_dev_data' has no member named 'acp_lock'
> 74 | spin_lock_irq(&adata->acp_lock);
> | ^~
> In file included from include/linux/kernel.h:21,
> from arch/x86/include/asm/percpu.h:27,
> from arch/x86/include/asm/current.h:6,
> from include/linux/sched.h:12,
> from include/linux/ratelimit.h:6,
> from include/linux/dev_printk.h:16,
> from include/linux/device.h:15,
> from include/linux/platform_device.h:13,
> from sound/soc/amd/acp/acp-i2s.c:15:
> sound/soc/amd/acp/acp-i2s.c:75:43: error: 'struct acp_dev_data' has no member named 'stream_list'
> 75 | list_for_each_entry(stream, &adata->stream_list, list) {
> | ^~
> include/linux/container_of.h:18:33: note: in definition of macro 'container_of'
> 18 | void *__mptr = (void *)(ptr); \
> | ^~~
> include/linux/list.h:531:9: note: in expansion of macro 'list_entry'
> 531 | list_entry((ptr)->next, type, member)
> | ^~~~~~~~~~
> include/linux/list.h:674:20: note: in expansion of macro 'list_first_entry'
> 674 | for (pos = list_first_entry(head, typeof(*pos), member); \
> | ^~~~~~~~~~~~~~~~
> sound/soc/amd/acp/acp-i2s.c:75:9: note: in expansion of macro 'list_for_each_entry'
> 75 | list_for_each_entry(stream, &adata->stream_list, list) {
> | ^~~~~~~~~~~~~~~~~~~
> In file included from include/linux/bits.h:22,
> from include/linux/ratelimit_types.h:5,
> from include/linux/ratelimit.h:5,
> from include/linux/dev_printk.h:16,
> from include/linux/device.h:15,
> from include/linux/platform_device.h:13,
> from sound/soc/amd/acp/acp-i2s.c:15:
> sound/soc/amd/acp/acp-i2s.c:75:43: error: 'struct acp_dev_data' has no member named 'stream_list'
> 75 | list_for_each_entry(stream, &adata->stream_list, list) {
> | ^~
> include/linux/build_bug.h:78:56: note: in definition of macro '__static_assert'
> 78 | #define __static_assert(expr, msg, ...) _Static_assert(expr, msg)
> | ^~~~
> include/linux/container_of.h:19:9: note: in expansion of macro 'static_assert'
> 19 | static_assert(__same_type(*(ptr), ((type *)0)->member) || \
> | ^~~~~~~~~~~~~
> include/linux/container_of.h:19:23: note: in expansion of macro '__same_type'
> 19 | static_assert(__same_type(*(ptr), ((type *)0)->member) || \
> | ^~~~~~~~~~~
> include/linux/list.h:520:9: note: in expansion of macro 'container_of'
> 520 | container_of(ptr, type, member)
> | ^~~~~~~~~~~~
> include/linux/list.h:531:9: note: in expansion of macro 'list_entry'
> 531 | list_entry((ptr)->next, type, member)
> | ^~~~~~~~~~
> include/linux/list.h:674:20: note: in expansion of macro 'list_first_entry'
> 674 | for (pos = list_first_entry(head, typeof(*pos), member); \
> | ^~~~~~~~~~~~~~~~
> sound/soc/amd/acp/acp-i2s.c:75:9: note: in expansion of macro 'list_for_each_entry'
> 75 | list_for_each_entry(stream, &adata->stream_list, list) {
> | ^~~~~~~~~~~~~~~~~~~
> include/linux/container_of.h:19:54: error: 'struct acp_stream' has no member named 'list'
> 19 | static_assert(__same_type(*(ptr), ((type *)0)->member) || \
> | ^~
> include/linux/build_bug.h:78:56: note: in definition of macro '__static_assert'
> 78 | #define __static_assert(expr, msg, ...) _Static_assert(expr, msg)
> | ^~~~
> include/linux/container_of.h:19:9: note: in expansion of macro 'static_assert'
> 19 | static_assert(__same_type(*(ptr), ((type *)0)->member) || \
> | ^~~~~~~~~~~~~
> include/linux/container_of.h:19:23: note: in expansion of macro '__same_type'
> 19 | static_assert(__same_type(*(ptr), ((type *)0)->member) || \
> | ^~~~~~~~~~~
> include/linux/list.h:520:9: note: in expansion of macro 'container_of'
> 520 | container_of(ptr, type, member)
> | ^~~~~~~~~~~~
> include/linux/list.h:531:9: note: in expansion of macro 'list_entry'
> 531 | list_entry((ptr)->next, type, member)
> | ^~~~~~~~~~
> include/linux/list.h:674:20: note: in expansion of macro 'list_first_entry'
> 674 | for (pos = list_first_entry(head, typeof(*pos), member); \
> | ^~~~~~~~~~~~~~~~
> sound/soc/amd/acp/acp-i2s.c:75:9: note: in expansion of macro 'list_for_each_entry'
> 75 | list_for_each_entry(stream, &adata->stream_list, list) {
> | ^~~~~~~~~~~~~~~~~~~
> sound/soc/amd/acp/acp-i2s.c:75:43: error: 'struct acp_dev_data' has no member named 'stream_list'
> 75 | list_for_each_entry(stream, &adata->stream_list, list) {
> | ^~
> include/linux/build_bug.h:78:56: note: in definition of macro '__static_assert'
> 78 | #define __static_assert(expr, msg, ...) _Static_assert(expr, msg)
> | ^~~~
> include/linux/container_of.h:19:9: note: in expansion of macro 'static_assert'
> 19 | static_assert(__same_type(*(ptr), ((type *)0)->member) || \
> | ^~~~~~~~~~~~~
> include/linux/container_of.h:20:23: note: in expansion of macro '__same_type'
> 20 | __same_type(*(ptr), void), \
> | ^~~~~~~~~~~
> include/linux/list.h:520:9: note: in expansion of macro 'container_of'
> 520 | container_of(ptr, type, member)
> | ^~~~~~~~~~~~
> include/linux/list.h:531:9: note: in expansion of macro 'list_entry'
> 531 | list_entry((ptr)->next, type, member)
> | ^~~~~~~~~~
> include/linux/list.h:674:20: note: in expansion of macro 'list_first_entry'
This patch is dependent on below patch, we will send these two patches
in one series.
depends on :-
https://patchwork.kernel.org/project/alsa-devel/patch/20220804072556.601396-1-venkataprasad.potturu@amd.com/
>
>
> vim +74 sound/soc/amd/acp/acp-i2s.c
>
> 47
> 48 static int acp_i2s_set_tdm_slot(struct snd_soc_dai *dai, u32 tx_mask, u32 rx_mask,
> 49 int slots, int slot_width)
> 50 {
> 51 struct device *dev = dai->component->dev;
> 52 struct acp_dev_data *adata = snd_soc_dai_get_drvdata(dai);
> 53 struct acp_stream *stream;
> 54 int slot_len;
> 55
> 56 switch (slot_width) {
> 57 case SLOT_WIDTH_8:
> 58 slot_len = 8;
> 59 break;
> 60 case SLOT_WIDTH_16:
> 61 slot_len = 16;
> 62 break;
> 63 case SLOT_WIDTH_24:
> 64 slot_len = 24;
> 65 break;
> 66 case SLOT_WIDTH_32:
> 67 slot_len = 0;
> 68 break;
> 69 default:
> 70 dev_err(dev, "Unsupported bitdepth %d\n", slot_width);
> 71 return -EINVAL;
> 72 }
> 73
> > 74 spin_lock_irq(&adata->acp_lock);
> 75 list_for_each_entry(stream, &adata->stream_list, list) {
> 76 if (tx_mask && stream->dir == SNDRV_PCM_STREAM_PLAYBACK)
> 77 adata->tdm_tx_fmt[stream->dai_id - 1] =
> 78 FRM_LEN | (slots << 15) | (slot_len << 18);
> 79 else if (rx_mask && stream->dir == SNDRV_PCM_STREAM_CAPTURE)
> 80 adata->tdm_rx_fmt[stream->dai_id - 1] =
> 81 FRM_LEN | (slots << 15) | (slot_len << 18);
> 82 }
> 83 spin_unlock_irq(&adata->acp_lock);
> 84 return 0;
> 85 }
> 86
>
> --
^ permalink raw reply [flat|nested] 2+ messages in thread
end of thread, other threads:[~2022-08-10 13:13 UTC | newest]
Thread overview: 2+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2022-08-05 6:04 [PATCH v2] ASoC: amd: acp: Add TDM support for acp i2s stream Venkata Prasad Potturu
[not found] ` <202208071454.7YeHuTDb-lkp@intel.com>
2022-08-10 13:15 ` Venkata Prasad Potturu
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).