* [PATCH v9 8/9] dt-bindings: media: Add MT8189 mediatek,vcodec-encoder
From: Kyrie Wu @ 2026-04-24 3:05 UTC (permalink / raw)
To: Tiffany Lin, Andrew-CT Chen, Yunfei Dong, Mauro Carvalho Chehab,
Rob Herring, Krzysztof Kozlowski, Conor Dooley, Matthias Brugger,
AngeloGioacchino Del Regno, Kyrie Wu, Hans Verkuil,
Nicolas Dufresne, Nathan Hebert, Arnd Bergmann, Irui Wang,
George Sun, linux-media, devicetree, linux-kernel,
linux-arm-kernel, linux-mediatek
Cc: Neil Armstrong, Andrzej Pietrasiewicz, Yilong Zhou,
Krzysztof Kozlowski
In-Reply-To: <20260424030527.10656-1-kyrie.wu@mediatek.com>
Add MT8189 encoder compatible string to distinguish former ICs
MTK's. Compared with MT8196, the maximum resolution of MT8189
encoder is only 4K, and the fps is only 30, which cannot reach
the highest parameter of MT8196: level6.2, 8K@60fps.
Compared with MT8188, the level can only support 5.1, which is less
than 5.2 of MT8188. But the maximum bitrate is 100Mbps, which is twice
that of MT8188. And MT8189 could support NBM mode.
Signed-off-by: Kyrie Wu <kyrie.wu@mediatek.com>
Acked-by: Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>
Reviewed-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>
---
.../devicetree/bindings/media/mediatek,vcodec-encoder.yaml | 2 ++
1 file changed, 2 insertions(+)
diff --git a/Documentation/devicetree/bindings/media/mediatek,vcodec-encoder.yaml b/Documentation/devicetree/bindings/media/mediatek,vcodec-encoder.yaml
index 72698456374a..91e1e0151e03 100644
--- a/Documentation/devicetree/bindings/media/mediatek,vcodec-encoder.yaml
+++ b/Documentation/devicetree/bindings/media/mediatek,vcodec-encoder.yaml
@@ -22,6 +22,7 @@ properties:
- mediatek,mt8173-vcodec-enc
- mediatek,mt8183-vcodec-enc
- mediatek,mt8188-vcodec-enc
+ - mediatek,mt8189-vcodec-enc
- mediatek,mt8192-vcodec-enc
- mediatek,mt8195-vcodec-enc
- mediatek,mt8196-vcodec-enc
@@ -105,6 +106,7 @@ allOf:
enum:
- mediatek,mt8183-vcodec-enc
- mediatek,mt8188-vcodec-enc
+ - mediatek,mt8189-vcodec-enc
- mediatek,mt8192-vcodec-enc
- mediatek,mt8195-vcodec-enc
--
2.45.2
^ permalink raw reply related
* [PATCH v9 2/9] media: mediatek: decoder: Add a new platform data member
From: Kyrie Wu @ 2026-04-24 3:05 UTC (permalink / raw)
To: Tiffany Lin, Andrew-CT Chen, Yunfei Dong, Mauro Carvalho Chehab,
Rob Herring, Krzysztof Kozlowski, Conor Dooley, Matthias Brugger,
AngeloGioacchino Del Regno, Kyrie Wu, Hans Verkuil,
Nicolas Dufresne, Nathan Hebert, Arnd Bergmann, Irui Wang,
George Sun, linux-media, devicetree, linux-kernel,
linux-arm-kernel, linux-mediatek
Cc: Neil Armstrong, Andrzej Pietrasiewicz, Yilong Zhou
In-Reply-To: <20260424030527.10656-1-kyrie.wu@mediatek.com>
Move the chip model information into the codec match data
and remove the second compatible matching code.
Signed-off-by: Kyrie Wu <kyrie.wu@mediatek.com>
Reviewed-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>
Reviewed-by: Nicolas Dufresne <nicolas.dufresne@collabora.com>
---
.../mediatek/vcodec/decoder/mtk_vcodec_dec.c | 2 +-
.../mediatek/vcodec/decoder/mtk_vcodec_dec.h | 5 +
.../vcodec/decoder/mtk_vcodec_dec_drv.c | 39 ++-----
.../vcodec/decoder/mtk_vcodec_dec_drv.h | 17 +--
.../vcodec/decoder/mtk_vcodec_dec_hw.c | 2 +-
.../vcodec/decoder/mtk_vcodec_dec_stateful.c | 1 +
.../vcodec/decoder/mtk_vcodec_dec_stateless.c | 104 +++++++++++++-----
7 files changed, 96 insertions(+), 74 deletions(-)
diff --git a/drivers/media/platform/mediatek/vcodec/decoder/mtk_vcodec_dec.c b/drivers/media/platform/mediatek/vcodec/decoder/mtk_vcodec_dec.c
index d76e891f784b..13d70acda88b 100644
--- a/drivers/media/platform/mediatek/vcodec/decoder/mtk_vcodec_dec.c
+++ b/drivers/media/platform/mediatek/vcodec/decoder/mtk_vcodec_dec.c
@@ -263,7 +263,7 @@ static int vidioc_vdec_querycap(struct file *file, void *priv,
struct device *dev = &ctx->dev->plat_dev->dev;
strscpy(cap->driver, dev->driver->name, sizeof(cap->driver));
- snprintf(cap->card, sizeof(cap->card), "MT%d video decoder", ctx->dev->chip_name);
+ snprintf(cap->card, sizeof(cap->card), "MT%d video decoder", ctx->dev->chip_model);
return 0;
}
diff --git a/drivers/media/platform/mediatek/vcodec/decoder/mtk_vcodec_dec.h b/drivers/media/platform/mediatek/vcodec/decoder/mtk_vcodec_dec.h
index 1af075fc0194..80cb46f1cded 100644
--- a/drivers/media/platform/mediatek/vcodec/decoder/mtk_vcodec_dec.h
+++ b/drivers/media/platform/mediatek/vcodec/decoder/mtk_vcodec_dec.h
@@ -69,6 +69,11 @@ extern const struct v4l2_m2m_ops mtk_vdec_m2m_ops;
extern const struct media_device_ops mtk_vcodec_media_ops;
extern const struct mtk_vcodec_dec_pdata mtk_vdec_8173_pdata;
extern const struct mtk_vcodec_dec_pdata mtk_vdec_8183_pdata;
+extern const struct mtk_vcodec_dec_pdata mtk_vdec_8186_pdata;
+extern const struct mtk_vcodec_dec_pdata mtk_vdec_8188_pdata;
+extern const struct mtk_vcodec_dec_pdata mtk_vdec_8192_pdata;
+extern const struct mtk_vcodec_dec_pdata mtk_vdec_8195_pdata;
+extern const struct mtk_vcodec_dec_pdata mtk_vdec_8196_pdata;
extern const struct mtk_vcodec_dec_pdata mtk_lat_sig_core_pdata;
extern const struct mtk_vcodec_dec_pdata mtk_vdec_single_core_pdata;
diff --git a/drivers/media/platform/mediatek/vcodec/decoder/mtk_vcodec_dec_drv.c b/drivers/media/platform/mediatek/vcodec/decoder/mtk_vcodec_dec_drv.c
index e7c140b26955..6ebd82ba8d23 100644
--- a/drivers/media/platform/mediatek/vcodec/decoder/mtk_vcodec_dec_drv.c
+++ b/drivers/media/platform/mediatek/vcodec/decoder/mtk_vcodec_dec_drv.c
@@ -331,26 +331,9 @@ static const struct v4l2_file_operations mtk_vcodec_fops = {
.mmap = v4l2_m2m_fop_mmap,
};
-static void mtk_vcodec_dec_get_chip_name(struct mtk_vcodec_dec_dev *vdec_dev)
+static void mtk_vcodec_dec_get_chip_model(struct mtk_vcodec_dec_dev *vdec_dev)
{
- struct device *dev = &vdec_dev->plat_dev->dev;
-
- if (of_device_is_compatible(dev->of_node, "mediatek,mt8173-vcodec-dec"))
- vdec_dev->chip_name = MTK_VDEC_MT8173;
- else if (of_device_is_compatible(dev->of_node, "mediatek,mt8183-vcodec-dec"))
- vdec_dev->chip_name = MTK_VDEC_MT8183;
- else if (of_device_is_compatible(dev->of_node, "mediatek,mt8192-vcodec-dec"))
- vdec_dev->chip_name = MTK_VDEC_MT8192;
- else if (of_device_is_compatible(dev->of_node, "mediatek,mt8195-vcodec-dec"))
- vdec_dev->chip_name = MTK_VDEC_MT8195;
- else if (of_device_is_compatible(dev->of_node, "mediatek,mt8186-vcodec-dec"))
- vdec_dev->chip_name = MTK_VDEC_MT8186;
- else if (of_device_is_compatible(dev->of_node, "mediatek,mt8188-vcodec-dec"))
- vdec_dev->chip_name = MTK_VDEC_MT8188;
- else if (of_device_is_compatible(dev->of_node, "mediatek,mt8196-vcodec-dec"))
- vdec_dev->chip_name = MTK_VDEC_MT8196;
- else
- vdec_dev->chip_name = MTK_VDEC_INVAL;
+ vdec_dev->chip_model = vdec_dev->vdec_pdata->chip_model;
}
static int mtk_vcodec_probe(struct platform_device *pdev)
@@ -368,11 +351,7 @@ static int mtk_vcodec_probe(struct platform_device *pdev)
INIT_LIST_HEAD(&dev->ctx_list);
dev->plat_dev = pdev;
- mtk_vcodec_dec_get_chip_name(dev);
- if (dev->chip_name == MTK_VDEC_INVAL) {
- dev_err(&pdev->dev, "Failed to get decoder chip name");
- return -EINVAL;
- }
+ mtk_vcodec_dec_get_chip_model(dev);
dev->vdec_pdata = of_device_get_match_data(&pdev->dev);
if (!of_property_read_u32(pdev->dev.of_node, "mediatek,vpu",
@@ -389,7 +368,7 @@ static int mtk_vcodec_probe(struct platform_device *pdev)
return -ENODEV;
}
dma_set_max_seg_size(&pdev->dev, UINT_MAX);
- if (dev->chip_name == MTK_VDEC_MT8196) {
+ if (dev->chip_model == 8196) {
ret = dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(36));
if (ret) {
dev_err(&pdev->dev, "Failed to enable 36-bit DMA: %d\n", ret);
@@ -558,23 +537,23 @@ static const struct of_device_id mtk_vcodec_match[] = {
},
{
.compatible = "mediatek,mt8192-vcodec-dec",
- .data = &mtk_lat_sig_core_pdata,
+ .data = &mtk_vdec_8192_pdata,
},
{
.compatible = "mediatek,mt8186-vcodec-dec",
- .data = &mtk_vdec_single_core_pdata,
+ .data = &mtk_vdec_8186_pdata,
},
{
.compatible = "mediatek,mt8195-vcodec-dec",
- .data = &mtk_lat_sig_core_pdata,
+ .data = &mtk_vdec_8195_pdata,
},
{
.compatible = "mediatek,mt8188-vcodec-dec",
- .data = &mtk_lat_sig_core_pdata,
+ .data = &mtk_vdec_8188_pdata,
},
{
.compatible = "mediatek,mt8196-vcodec-dec",
- .data = &mtk_lat_sig_core_pdata,
+ .data = &mtk_vdec_8196_pdata,
},
{},
};
diff --git a/drivers/media/platform/mediatek/vcodec/decoder/mtk_vcodec_dec_drv.h b/drivers/media/platform/mediatek/vcodec/decoder/mtk_vcodec_dec_drv.h
index f06dfc1a3455..7921588bf814 100644
--- a/drivers/media/platform/mediatek/vcodec/decoder/mtk_vcodec_dec_drv.h
+++ b/drivers/media/platform/mediatek/vcodec/decoder/mtk_vcodec_dec_drv.h
@@ -21,17 +21,6 @@
#define IS_VDEC_INNER_RACING(capability) ((capability) & MTK_VCODEC_INNER_RACING)
#define IS_VDEC_SUPPORT_EXT(capability) ((capability) & MTK_VDEC_IS_SUPPORT_EXT)
-enum mtk_vcodec_dec_chip_name {
- MTK_VDEC_INVAL = 0,
- MTK_VDEC_MT8173 = 8173,
- MTK_VDEC_MT8183 = 8183,
- MTK_VDEC_MT8186 = 8186,
- MTK_VDEC_MT8188 = 8188,
- MTK_VDEC_MT8192 = 8192,
- MTK_VDEC_MT8195 = 8195,
- MTK_VDEC_MT8196 = 8196,
-};
-
/*
* enum mtk_vdec_format_types - Structure used to get supported
* format types according to decoder capability
@@ -108,6 +97,7 @@ struct vdec_pic_info {
*
* @is_subdev_supported: whether support parent-node architecture(subdev)
* @uses_stateless_api: whether the decoder uses the stateless API with requests
+ * @chip_model: platforms configuration values
*/
struct mtk_vcodec_dec_pdata {
void (*init_vdec_params)(struct mtk_vcodec_dec_ctx *ctx);
@@ -129,6 +119,7 @@ struct mtk_vcodec_dec_pdata {
bool is_subdev_supported;
bool uses_stateless_api;
+ unsigned int chip_model;
};
/**
@@ -276,7 +267,7 @@ struct mtk_vcodec_dec_ctx {
* @dec_racing_info_mutex: mutex lock used for inner racing mode
* @dbgfs: debug log related information
*
- * @chip_name: used to distinguish platforms and select the correct codec configuration values
+ * @chip_model: used to distinguish platforms and select the correct codec configuration values
*/
struct mtk_vcodec_dec_dev {
struct v4l2_device v4l2_dev;
@@ -319,7 +310,7 @@ struct mtk_vcodec_dec_dev {
struct mutex dec_racing_info_mutex;
struct mtk_vcodec_dbgfs dbgfs;
- enum mtk_vcodec_dec_chip_name chip_name;
+ unsigned int chip_model;
};
static inline struct mtk_vcodec_dec_ctx *fh_to_dec_ctx(struct v4l2_fh *fh)
diff --git a/drivers/media/platform/mediatek/vcodec/decoder/mtk_vcodec_dec_hw.c b/drivers/media/platform/mediatek/vcodec/decoder/mtk_vcodec_dec_hw.c
index e4e527fe54dc..149f1ad58152 100644
--- a/drivers/media/platform/mediatek/vcodec/decoder/mtk_vcodec_dec_hw.c
+++ b/drivers/media/platform/mediatek/vcodec/decoder/mtk_vcodec_dec_hw.c
@@ -76,7 +76,7 @@ static void mtk_vdec_hw_clean_xpc(struct mtk_vdec_hw_dev *dev)
{
u32 val, mask, addr = VDEC_XPC_CLEAN_ADDR;
- if (dev->main_dev->chip_name != MTK_VDEC_MT8196)
+ if (dev->main_dev->chip_model != 8196)
return;
val = dev->hw_idx == MTK_VDEC_LAT0 ? VDEC_XPC_LAT_VAL : VDEC_XPC_CORE_VAL;
diff --git a/drivers/media/platform/mediatek/vcodec/decoder/mtk_vcodec_dec_stateful.c b/drivers/media/platform/mediatek/vcodec/decoder/mtk_vcodec_dec_stateful.c
index aa9bdee7a96c..0e702d6a43ed 100644
--- a/drivers/media/platform/mediatek/vcodec/decoder/mtk_vcodec_dec_stateful.c
+++ b/drivers/media/platform/mediatek/vcodec/decoder/mtk_vcodec_dec_stateful.c
@@ -618,4 +618,5 @@ const struct mtk_vcodec_dec_pdata mtk_vdec_8173_pdata = {
.flush_decoder = mtk_vdec_flush_decoder,
.is_subdev_supported = false,
.hw_arch = MTK_VDEC_PURE_SINGLE_CORE,
+ .chip_model = 8173,
};
diff --git a/drivers/media/platform/mediatek/vcodec/decoder/mtk_vcodec_dec_stateless.c b/drivers/media/platform/mediatek/vcodec/decoder/mtk_vcodec_dec_stateless.c
index 472ece5713a5..5ecbfc169805 100644
--- a/drivers/media/platform/mediatek/vcodec/decoder/mtk_vcodec_dec_stateless.c
+++ b/drivers/media/platform/mediatek/vcodec/decoder/mtk_vcodec_dec_stateless.c
@@ -571,17 +571,17 @@ static const struct v4l2_ctrl_ops mtk_vcodec_dec_ctrl_ops = {
static void mtk_vcodec_dec_fill_h264_level(struct v4l2_ctrl_config *cfg,
struct mtk_vcodec_dec_ctx *ctx)
{
- switch (ctx->dev->chip_name) {
- case MTK_VDEC_MT8192:
- case MTK_VDEC_MT8188:
+ switch (ctx->dev->chip_model) {
+ case 8192:
+ case 8188:
cfg->max = V4L2_MPEG_VIDEO_H264_LEVEL_5_2;
break;
- case MTK_VDEC_MT8195:
- case MTK_VDEC_MT8196:
+ case 8195:
+ case 8196:
cfg->max = V4L2_MPEG_VIDEO_H264_LEVEL_6_0;
break;
- case MTK_VDEC_MT8183:
- case MTK_VDEC_MT8186:
+ case 8183:
+ case 8186:
cfg->max = V4L2_MPEG_VIDEO_H264_LEVEL_4_2;
break;
default:
@@ -593,10 +593,10 @@ static void mtk_vcodec_dec_fill_h264_level(struct v4l2_ctrl_config *cfg,
static void mtk_vcodec_dec_fill_h264_profile(struct v4l2_ctrl_config *cfg,
struct mtk_vcodec_dec_ctx *ctx)
{
- switch (ctx->dev->chip_name) {
- case MTK_VDEC_MT8188:
- case MTK_VDEC_MT8195:
- case MTK_VDEC_MT8196:
+ switch (ctx->dev->chip_model) {
+ case 8188:
+ case 8195:
+ case 8196:
cfg->max = V4L2_MPEG_VIDEO_H264_PROFILE_HIGH_10;
break;
default:
@@ -608,12 +608,12 @@ static void mtk_vcodec_dec_fill_h264_profile(struct v4l2_ctrl_config *cfg,
static void mtk_vcodec_dec_fill_h265_level(struct v4l2_ctrl_config *cfg,
struct mtk_vcodec_dec_ctx *ctx)
{
- switch (ctx->dev->chip_name) {
- case MTK_VDEC_MT8188:
+ switch (ctx->dev->chip_model) {
+ case 8188:
cfg->max = V4L2_MPEG_VIDEO_HEVC_LEVEL_5_1;
break;
- case MTK_VDEC_MT8195:
- case MTK_VDEC_MT8196:
+ case 8195:
+ case 8196:
cfg->max = V4L2_MPEG_VIDEO_HEVC_LEVEL_5_2;
break;
default:
@@ -625,10 +625,10 @@ static void mtk_vcodec_dec_fill_h265_level(struct v4l2_ctrl_config *cfg,
static void mtk_vcodec_dec_fill_h265_profile(struct v4l2_ctrl_config *cfg,
struct mtk_vcodec_dec_ctx *ctx)
{
- switch (ctx->dev->chip_name) {
- case MTK_VDEC_MT8188:
- case MTK_VDEC_MT8195:
- case MTK_VDEC_MT8196:
+ switch (ctx->dev->chip_model) {
+ case 8188:
+ case 8195:
+ case 8196:
cfg->max = V4L2_MPEG_VIDEO_HEVC_PROFILE_MAIN_10;
break;
default:
@@ -640,16 +640,16 @@ static void mtk_vcodec_dec_fill_h265_profile(struct v4l2_ctrl_config *cfg,
static void mtk_vcodec_dec_fill_vp9_level(struct v4l2_ctrl_config *cfg,
struct mtk_vcodec_dec_ctx *ctx)
{
- switch (ctx->dev->chip_name) {
- case MTK_VDEC_MT8192:
- case MTK_VDEC_MT8188:
+ switch (ctx->dev->chip_model) {
+ case 8192:
+ case 8188:
cfg->max = V4L2_MPEG_VIDEO_VP9_LEVEL_5_1;
break;
- case MTK_VDEC_MT8195:
- case MTK_VDEC_MT8196:
+ case 8195:
+ case 8196:
cfg->max = V4L2_MPEG_VIDEO_VP9_LEVEL_5_2;
break;
- case MTK_VDEC_MT8186:
+ case 8186:
cfg->max = V4L2_MPEG_VIDEO_VP9_LEVEL_4_1;
break;
default:
@@ -661,10 +661,10 @@ static void mtk_vcodec_dec_fill_vp9_level(struct v4l2_ctrl_config *cfg,
static void mtk_vcodec_dec_fill_vp9_profile(struct v4l2_ctrl_config *cfg,
struct mtk_vcodec_dec_ctx *ctx)
{
- switch (ctx->dev->chip_name) {
- case MTK_VDEC_MT8188:
- case MTK_VDEC_MT8195:
- case MTK_VDEC_MT8196:
+ switch (ctx->dev->chip_model) {
+ case 8188:
+ case 8195:
+ case 8196:
cfg->max = V4L2_MPEG_VIDEO_VP9_PROFILE_2;
break;
default:
@@ -935,6 +935,7 @@ const struct mtk_vcodec_dec_pdata mtk_vdec_8183_pdata = {
.get_cap_buffer = vdec_get_cap_buffer,
.is_subdev_supported = false,
.hw_arch = MTK_VDEC_PURE_SINGLE_CORE,
+ .chip_model = 8183,
};
/* This platform data is used for one lat and one core architecture. */
@@ -955,6 +956,45 @@ const struct mtk_vcodec_dec_pdata mtk_lat_sig_core_pdata = {
.hw_arch = MTK_VDEC_LAT_SINGLE_CORE,
};
+#define MTK_STATELESS_DEC_DATA \
+ .init_vdec_params = mtk_init_vdec_params, \
+ .ctrls_setup = mtk_vcodec_dec_ctrls_setup, \
+ .vdec_vb2_ops = &mtk_vdec_request_vb2_ops, \
+ .vdec_formats = mtk_video_formats, \
+ .num_formats = &num_formats, \
+ .default_out_fmt = &default_out_format, \
+ .default_cap_fmt = &default_cap_format, \
+ .uses_stateless_api = true, \
+ .worker = mtk_vdec_worker, \
+ .flush_decoder = mtk_vdec_flush_decoder, \
+ .cap_to_disp = mtk_vdec_stateless_cap_to_disp, \
+ .get_cap_buffer = vdec_get_cap_buffer, \
+ .is_subdev_supported = true
+
+const struct mtk_vcodec_dec_pdata mtk_vdec_8188_pdata = {
+ MTK_STATELESS_DEC_DATA,
+ .hw_arch = MTK_VDEC_LAT_SINGLE_CORE,
+ .chip_model = 8188,
+};
+
+const struct mtk_vcodec_dec_pdata mtk_vdec_8192_pdata = {
+ MTK_STATELESS_DEC_DATA,
+ .hw_arch = MTK_VDEC_LAT_SINGLE_CORE,
+ .chip_model = 8192,
+};
+
+const struct mtk_vcodec_dec_pdata mtk_vdec_8195_pdata = {
+ MTK_STATELESS_DEC_DATA,
+ .hw_arch = MTK_VDEC_LAT_SINGLE_CORE,
+ .chip_model = 8195,
+};
+
+const struct mtk_vcodec_dec_pdata mtk_vdec_8196_pdata = {
+ MTK_STATELESS_DEC_DATA,
+ .hw_arch = MTK_VDEC_LAT_SINGLE_CORE,
+ .chip_model = 8196,
+};
+
const struct mtk_vcodec_dec_pdata mtk_vdec_single_core_pdata = {
.init_vdec_params = mtk_init_vdec_params,
.ctrls_setup = mtk_vcodec_dec_ctrls_setup,
@@ -971,3 +1011,9 @@ const struct mtk_vcodec_dec_pdata mtk_vdec_single_core_pdata = {
.is_subdev_supported = true,
.hw_arch = MTK_VDEC_PURE_SINGLE_CORE,
};
+
+const struct mtk_vcodec_dec_pdata mtk_vdec_8186_pdata = {
+ MTK_STATELESS_DEC_DATA,
+ .hw_arch = MTK_VDEC_PURE_SINGLE_CORE,
+ .chip_model = 8186,
+};
--
2.45.2
^ permalink raw reply related
* [PATCH v9 4/9] media: mediatek: vcodec: Add VP9 Probability Size Configuration
From: Kyrie Wu @ 2026-04-24 3:05 UTC (permalink / raw)
To: Tiffany Lin, Andrew-CT Chen, Yunfei Dong, Mauro Carvalho Chehab,
Rob Herring, Krzysztof Kozlowski, Conor Dooley, Matthias Brugger,
AngeloGioacchino Del Regno, Kyrie Wu, Hans Verkuil,
Nicolas Dufresne, Nathan Hebert, Arnd Bergmann, Irui Wang,
George Sun, linux-media, devicetree, linux-kernel,
linux-arm-kernel, linux-mediatek
Cc: Neil Armstrong, Andrzej Pietrasiewicz, Yilong Zhou
In-Reply-To: <20260424030527.10656-1-kyrie.wu@mediatek.com>
Introduce support for using different probability buffer sizes for
different stateless decoders: in particular, the VP9 decoder can use
a different size on different SoCs because of different
hardware capabilities.
Move the hardcoded single probability buffer size value to
decoder params, introduce a new VP9_4K_PROB_BUF_SIZE and assign:
- VP9_PROB_BUF_SIZE (2560 lines) to legacy SoCs;
- VP9_4K_PROB_BUF_SIZE (3840 lines) to newer SoCs (MT8196, MT8189).
Signed-off-by: Kyrie Wu <kyrie.wu@mediatek.com>
Reviewed-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>
---
.../mediatek/vcodec/decoder/mtk_vcodec_dec_drv.h | 2 ++
.../mediatek/vcodec/decoder/mtk_vcodec_dec_stateful.c | 1 +
.../mediatek/vcodec/decoder/mtk_vcodec_dec_stateless.c | 9 +++++++++
.../mediatek/vcodec/decoder/vdec/vdec_vp9_req_lat_if.c | 4 ++--
4 files changed, 14 insertions(+), 2 deletions(-)
diff --git a/drivers/media/platform/mediatek/vcodec/decoder/mtk_vcodec_dec_drv.h b/drivers/media/platform/mediatek/vcodec/decoder/mtk_vcodec_dec_drv.h
index 4ffc0eae855b..43dc0b22fdb0 100644
--- a/drivers/media/platform/mediatek/vcodec/decoder/mtk_vcodec_dec_drv.h
+++ b/drivers/media/platform/mediatek/vcodec/decoder/mtk_vcodec_dec_drv.h
@@ -82,10 +82,12 @@ struct vdec_pic_info {
* struct mtk_vcodec_dec_params - decoder supported parameters
* @level: decoder supported vcodec level
* @profile: decoder supported vcodec profile
+ * @prob_size: vp9 decoder probability size
*/
struct mtk_vcodec_dec_params {
s64 level;
s64 profile;
+ size_t prob_size;
};
/**
diff --git a/drivers/media/platform/mediatek/vcodec/decoder/mtk_vcodec_dec_stateful.c b/drivers/media/platform/mediatek/vcodec/decoder/mtk_vcodec_dec_stateful.c
index 64f32976d15e..5dcbe6550419 100644
--- a/drivers/media/platform/mediatek/vcodec/decoder/mtk_vcodec_dec_stateful.c
+++ b/drivers/media/platform/mediatek/vcodec/decoder/mtk_vcodec_dec_stateful.c
@@ -630,5 +630,6 @@ const struct mtk_vcodec_dec_pdata mtk_vdec_8173_pdata = {
.vp9_params = {
.level = V4L2_MPEG_VIDEO_VP9_LEVEL_4_0,
.profile = V4L2_MPEG_VIDEO_VP9_PROFILE_1,
+ .prob_size = 2560,
},
};
diff --git a/drivers/media/platform/mediatek/vcodec/decoder/mtk_vcodec_dec_stateless.c b/drivers/media/platform/mediatek/vcodec/decoder/mtk_vcodec_dec_stateless.c
index efcd28f5f289..783a988b894a 100644
--- a/drivers/media/platform/mediatek/vcodec/decoder/mtk_vcodec_dec_stateless.c
+++ b/drivers/media/platform/mediatek/vcodec/decoder/mtk_vcodec_dec_stateless.c
@@ -10,6 +10,9 @@
#include "mtk_vcodec_dec_pm.h"
#include "vdec_drv_if.h"
+#define VP9_PROB_BUF_SIZE 2560
+#define VP9_4K_PROB_BUF_SIZE 3840
+
/**
* struct mtk_stateless_control - CID control type
* @cfg: control configuration
@@ -890,6 +893,7 @@ const struct mtk_vcodec_dec_pdata mtk_vdec_8183_pdata = {
.vp9_params = {
.level = V4L2_MPEG_VIDEO_VP9_LEVEL_4_0,
.profile = V4L2_MPEG_VIDEO_VP9_PROFILE_1,
+ .prob_size = VP9_PROB_BUF_SIZE,
},
};
@@ -941,6 +945,7 @@ const struct mtk_vcodec_dec_pdata mtk_vdec_8188_pdata = {
.vp9_params = {
.level = V4L2_MPEG_VIDEO_VP9_LEVEL_5_1,
.profile = V4L2_MPEG_VIDEO_VP9_PROFILE_2,
+ .prob_size = VP9_PROB_BUF_SIZE,
},
};
@@ -959,6 +964,7 @@ const struct mtk_vcodec_dec_pdata mtk_vdec_8192_pdata = {
.vp9_params = {
.level = V4L2_MPEG_VIDEO_VP9_LEVEL_5_1,
.profile = V4L2_MPEG_VIDEO_VP9_PROFILE_2,
+ .prob_size = VP9_PROB_BUF_SIZE,
},
};
@@ -977,6 +983,7 @@ const struct mtk_vcodec_dec_pdata mtk_vdec_8195_pdata = {
.vp9_params = {
.level = V4L2_MPEG_VIDEO_VP9_LEVEL_5_1,
.profile = V4L2_MPEG_VIDEO_VP9_PROFILE_1,
+ .prob_size = VP9_PROB_BUF_SIZE,
},
};
@@ -995,6 +1002,7 @@ const struct mtk_vcodec_dec_pdata mtk_vdec_8196_pdata = {
.vp9_params = {
.level = V4L2_MPEG_VIDEO_VP9_LEVEL_5_2,
.profile = V4L2_MPEG_VIDEO_VP9_PROFILE_2,
+ .prob_size = VP9_4K_PROB_BUF_SIZE,
},
};
@@ -1030,5 +1038,6 @@ const struct mtk_vcodec_dec_pdata mtk_vdec_8186_pdata = {
.vp9_params = {
.level = V4L2_MPEG_VIDEO_VP9_LEVEL_4_1,
.profile = V4L2_MPEG_VIDEO_VP9_PROFILE_1,
+ .prob_size = VP9_PROB_BUF_SIZE,
},
};
diff --git a/drivers/media/platform/mediatek/vcodec/decoder/vdec/vdec_vp9_req_lat_if.c b/drivers/media/platform/mediatek/vcodec/decoder/vdec/vdec_vp9_req_lat_if.c
index 3f4b70526754..e02dcf81b3cb 100644
--- a/drivers/media/platform/mediatek/vcodec/decoder/vdec/vdec_vp9_req_lat_if.c
+++ b/drivers/media/platform/mediatek/vcodec/decoder/vdec/vdec_vp9_req_lat_if.c
@@ -22,7 +22,6 @@
#define VP9_RESET_FRAME_CONTEXT_ALL 3
#define VP9_TILE_BUF_SIZE 4096
-#define VP9_PROB_BUF_SIZE 2560
#define VP9_COUNTS_BUF_SIZE 16384
#define HDR_FLAG(x) (!!((hdr)->flags & V4L2_VP9_FRAME_FLAG_##x))
@@ -551,6 +550,7 @@ static int vdec_vp9_slice_alloc_working_buffer(struct vdec_vp9_slice_instance *i
struct vdec_vp9_slice_vsi *vsi)
{
struct mtk_vcodec_dec_ctx *ctx = instance->ctx;
+ struct mtk_vcodec_dec_dev *pdev = ctx->dev;
enum vdec_vp9_slice_resolution_level level;
/* super blocks */
unsigned int max_sb_w;
@@ -621,7 +621,7 @@ static int vdec_vp9_slice_alloc_working_buffer(struct vdec_vp9_slice_instance *i
}
if (!instance->prob.va) {
- instance->prob.size = VP9_PROB_BUF_SIZE;
+ instance->prob.size = pdev->vdec_pdata->vp9_params.prob_size;
if (mtk_vcodec_mem_alloc(ctx, &instance->prob))
goto err;
}
--
2.45.2
^ permalink raw reply related
* [PATCH v9 5/9] media: mediatek: vcodec: Fix vp9 4096x2176 fail for profile2
From: Kyrie Wu @ 2026-04-24 3:05 UTC (permalink / raw)
To: Tiffany Lin, Andrew-CT Chen, Yunfei Dong, Mauro Carvalho Chehab,
Rob Herring, Krzysztof Kozlowski, Conor Dooley, Matthias Brugger,
AngeloGioacchino Del Regno, Kyrie Wu, Hans Verkuil,
Nicolas Dufresne, Nathan Hebert, Arnd Bergmann, Irui Wang,
George Sun, linux-media, devicetree, linux-kernel,
linux-arm-kernel, linux-mediatek
Cc: Neil Armstrong, Andrzej Pietrasiewicz, Yilong Zhou
In-Reply-To: <20260424030527.10656-1-kyrie.wu@mediatek.com>
The DRAM address of the VP9 decoder tile info buffers may require
as much as 36bits for 4096x2176 resolution. Fold the 4 most significant
bits into the lower (padding) four bits of address.
Fixes: 5d418351ca8f1 ("media: mediatek: vcodec: support stateless VP9 decoding")
Signed-off-by: Kyrie Wu <kyrie.wu@mediatek.com>
Reviewed-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>
Reviewed-by: Nicolas Dufresne <nicolas.dufresne@collabora.com>
---
.../mediatek/vcodec/decoder/vdec/vdec_vp9_req_lat_if.c | 10 +++++++++-
1 file changed, 9 insertions(+), 1 deletion(-)
diff --git a/drivers/media/platform/mediatek/vcodec/decoder/vdec/vdec_vp9_req_lat_if.c b/drivers/media/platform/mediatek/vcodec/decoder/vdec/vdec_vp9_req_lat_if.c
index e02dcf81b3cb..c9eb9ebe4116 100644
--- a/drivers/media/platform/mediatek/vcodec/decoder/vdec/vdec_vp9_req_lat_if.c
+++ b/drivers/media/platform/mediatek/vcodec/decoder/vdec/vdec_vp9_req_lat_if.c
@@ -1138,9 +1138,17 @@ static int vdec_vp9_slice_setup_tile_buffer(struct vdec_vp9_slice_instance *inst
return -EINVAL;
}
tiles->size[i][j] = size;
+ /*
+ * If the system supports 64-bit DMA addresses, the upper 4 bits
+ * of the address are also encoded into the buffer entry.
+ * The buffer pointer (tb) is incremented after each entry is written.
+ */
if (tiles->mi_rows[i]) {
*tb++ = (size << 3) + ((offset << 3) & 0x7f);
- *tb++ = pa & ~0xf;
+ *tb = pa & GENMASK(31, 4);
+ if (IS_ENABLED(CONFIG_ARCH_DMA_ADDR_T_64BIT))
+ *tb |= (pa >> 32) & GENMASK(3, 0);
+ tb++;
*tb++ = (pa << 3) & 0x7f;
mi_row = (tiles->mi_rows[i] - 1) & 0x1ff;
mi_col = (tiles->mi_cols[j] - 1) & 0x3f;
--
2.45.2
^ permalink raw reply related
* [PATCH v9 1/9] dt-bindings: media: mediatek: decoder: Add MT8189 mediatek,vcodec-decoder
From: Kyrie Wu @ 2026-04-24 3:05 UTC (permalink / raw)
To: Tiffany Lin, Andrew-CT Chen, Yunfei Dong, Mauro Carvalho Chehab,
Rob Herring, Krzysztof Kozlowski, Conor Dooley, Matthias Brugger,
AngeloGioacchino Del Regno, Kyrie Wu, Hans Verkuil,
Nicolas Dufresne, Nathan Hebert, Arnd Bergmann, Irui Wang,
George Sun, linux-media, devicetree, linux-kernel,
linux-arm-kernel, linux-mediatek
Cc: Neil Armstrong, Andrzej Pietrasiewicz, Yilong Zhou
In-Reply-To: <20260424030527.10656-1-kyrie.wu@mediatek.com>
Add compatible for video decoder on MT8189 platform. Compared with
former ICs, the MT8189 decoder use iommu to instead of smmu, and
use scp architecture, the frequency is only 406MHZ, and cannot reach
more than 700MHZ. It uses only one clock. At the same time, the decoder
supports the vp9 decoding protocol for the first time in single IC.
Signed-off-by: Kyrie Wu <kyrie.wu@mediatek.com>
Acked-by: Rob Herring (Arm) <robh@kernel.org>
Reviewed-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>
Reviewed-by: Nicolas Dufresne <nicolas.dufresne@collabora.com>
---
.../bindings/media/mediatek,vcodec-subdev-decoder.yaml | 5 +++--
1 file changed, 3 insertions(+), 2 deletions(-)
diff --git a/Documentation/devicetree/bindings/media/mediatek,vcodec-subdev-decoder.yaml b/Documentation/devicetree/bindings/media/mediatek,vcodec-subdev-decoder.yaml
index 74e1d88d3056..ee2bbbdb2d50 100644
--- a/Documentation/devicetree/bindings/media/mediatek,vcodec-subdev-decoder.yaml
+++ b/Documentation/devicetree/bindings/media/mediatek,vcodec-subdev-decoder.yaml
@@ -75,6 +75,7 @@ properties:
- mediatek,mt8192-vcodec-dec
- mediatek,mt8186-vcodec-dec
- mediatek,mt8188-vcodec-dec
+ - mediatek,mt8189-vcodec-dec
- mediatek,mt8195-vcodec-dec
- mediatek,mt8196-vcodec-dec
@@ -132,11 +133,11 @@ patternProperties:
Refer to bindings/iommu/mediatek,iommu.yaml.
clocks:
- minItems: 4
+ minItems: 1
maxItems: 5
clock-names:
- minItems: 4
+ minItems: 1
maxItems: 5
assigned-clocks:
--
2.45.2
^ permalink raw reply related
* [PATCH v9 3/9] media: mediatek: vcodec: Refactor Decoder profile & level Handling
From: Kyrie Wu @ 2026-04-24 3:05 UTC (permalink / raw)
To: Tiffany Lin, Andrew-CT Chen, Yunfei Dong, Mauro Carvalho Chehab,
Rob Herring, Krzysztof Kozlowski, Conor Dooley, Matthias Brugger,
AngeloGioacchino Del Regno, Kyrie Wu, Hans Verkuil,
Nicolas Dufresne, Nathan Hebert, Arnd Bergmann, Irui Wang,
George Sun, linux-media, devicetree, linux-kernel,
linux-arm-kernel, linux-mediatek
Cc: Neil Armstrong, Andrzej Pietrasiewicz, Yilong Zhou
In-Reply-To: <20260424030527.10656-1-kyrie.wu@mediatek.com>
This commit refactors the handling of decoder parameters for H264,
H265, and VP9 codecs by introducing a new structure to standardize
supported level and profile information. By leveraging this change,
chipset-specific conditional logic in the codec configuration
functions is significantly reduced.
Signed-off-by: Kyrie Wu <kyrie.wu@mediatek.com>
Reviewed-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>
---
.../vcodec/decoder/mtk_vcodec_dec_drv.h | 16 ++
.../vcodec/decoder/mtk_vcodec_dec_stateful.c | 12 ++
.../vcodec/decoder/mtk_vcodec_dec_stateless.c | 165 ++++++++++--------
3 files changed, 118 insertions(+), 75 deletions(-)
diff --git a/drivers/media/platform/mediatek/vcodec/decoder/mtk_vcodec_dec_drv.h b/drivers/media/platform/mediatek/vcodec/decoder/mtk_vcodec_dec_drv.h
index 7921588bf814..4ffc0eae855b 100644
--- a/drivers/media/platform/mediatek/vcodec/decoder/mtk_vcodec_dec_drv.h
+++ b/drivers/media/platform/mediatek/vcodec/decoder/mtk_vcodec_dec_drv.h
@@ -78,6 +78,16 @@ struct vdec_pic_info {
unsigned int reserved;
};
+/**
+ * struct mtk_vcodec_dec_params - decoder supported parameters
+ * @level: decoder supported vcodec level
+ * @profile: decoder supported vcodec profile
+ */
+struct mtk_vcodec_dec_params {
+ s64 level;
+ s64 profile;
+};
+
/**
* struct mtk_vcodec_dec_pdata - compatible data for each IC
* @init_vdec_params: init vdec params
@@ -98,6 +108,9 @@ struct vdec_pic_info {
* @is_subdev_supported: whether support parent-node architecture(subdev)
* @uses_stateless_api: whether the decoder uses the stateless API with requests
* @chip_model: platforms configuration values
+ * @h264_params: H264 decoder default supported params
+ * @h265_params: H265 decoder default supported params
+ * @vp9_params: VP9 decoder default supported params
*/
struct mtk_vcodec_dec_pdata {
void (*init_vdec_params)(struct mtk_vcodec_dec_ctx *ctx);
@@ -120,6 +133,9 @@ struct mtk_vcodec_dec_pdata {
bool is_subdev_supported;
bool uses_stateless_api;
unsigned int chip_model;
+ struct mtk_vcodec_dec_params h264_params;
+ struct mtk_vcodec_dec_params h265_params;
+ struct mtk_vcodec_dec_params vp9_params;
};
/**
diff --git a/drivers/media/platform/mediatek/vcodec/decoder/mtk_vcodec_dec_stateful.c b/drivers/media/platform/mediatek/vcodec/decoder/mtk_vcodec_dec_stateful.c
index 0e702d6a43ed..64f32976d15e 100644
--- a/drivers/media/platform/mediatek/vcodec/decoder/mtk_vcodec_dec_stateful.c
+++ b/drivers/media/platform/mediatek/vcodec/decoder/mtk_vcodec_dec_stateful.c
@@ -619,4 +619,16 @@ const struct mtk_vcodec_dec_pdata mtk_vdec_8173_pdata = {
.is_subdev_supported = false,
.hw_arch = MTK_VDEC_PURE_SINGLE_CORE,
.chip_model = 8173,
+ .h264_params = {
+ .level = V4L2_MPEG_VIDEO_H264_LEVEL_4_1,
+ .profile = V4L2_MPEG_VIDEO_H264_PROFILE_HIGH,
+ },
+ .h265_params = {
+ .level = V4L2_MPEG_VIDEO_HEVC_LEVEL_4,
+ .profile = V4L2_MPEG_VIDEO_HEVC_PROFILE_MAIN_STILL_PICTURE,
+ },
+ .vp9_params = {
+ .level = V4L2_MPEG_VIDEO_VP9_LEVEL_4_0,
+ .profile = V4L2_MPEG_VIDEO_VP9_PROFILE_1,
+ },
};
diff --git a/drivers/media/platform/mediatek/vcodec/decoder/mtk_vcodec_dec_stateless.c b/drivers/media/platform/mediatek/vcodec/decoder/mtk_vcodec_dec_stateless.c
index 5ecbfc169805..efcd28f5f289 100644
--- a/drivers/media/platform/mediatek/vcodec/decoder/mtk_vcodec_dec_stateless.c
+++ b/drivers/media/platform/mediatek/vcodec/decoder/mtk_vcodec_dec_stateless.c
@@ -571,106 +571,49 @@ static const struct v4l2_ctrl_ops mtk_vcodec_dec_ctrl_ops = {
static void mtk_vcodec_dec_fill_h264_level(struct v4l2_ctrl_config *cfg,
struct mtk_vcodec_dec_ctx *ctx)
{
- switch (ctx->dev->chip_model) {
- case 8192:
- case 8188:
- cfg->max = V4L2_MPEG_VIDEO_H264_LEVEL_5_2;
- break;
- case 8195:
- case 8196:
- cfg->max = V4L2_MPEG_VIDEO_H264_LEVEL_6_0;
- break;
- case 8183:
- case 8186:
- cfg->max = V4L2_MPEG_VIDEO_H264_LEVEL_4_2;
- break;
- default:
- cfg->max = V4L2_MPEG_VIDEO_H264_LEVEL_4_1;
- break;
- }
+ struct mtk_vcodec_dec_dev *pdev = ctx->dev;
+
+ cfg->max = pdev->vdec_pdata->h264_params.level;
}
static void mtk_vcodec_dec_fill_h264_profile(struct v4l2_ctrl_config *cfg,
struct mtk_vcodec_dec_ctx *ctx)
{
- switch (ctx->dev->chip_model) {
- case 8188:
- case 8195:
- case 8196:
- cfg->max = V4L2_MPEG_VIDEO_H264_PROFILE_HIGH_10;
- break;
- default:
- cfg->max = V4L2_MPEG_VIDEO_H264_PROFILE_HIGH;
- break;
- }
+ struct mtk_vcodec_dec_dev *pdev = ctx->dev;
+
+ cfg->max = pdev->vdec_pdata->h264_params.profile;
}
static void mtk_vcodec_dec_fill_h265_level(struct v4l2_ctrl_config *cfg,
struct mtk_vcodec_dec_ctx *ctx)
{
- switch (ctx->dev->chip_model) {
- case 8188:
- cfg->max = V4L2_MPEG_VIDEO_HEVC_LEVEL_5_1;
- break;
- case 8195:
- case 8196:
- cfg->max = V4L2_MPEG_VIDEO_HEVC_LEVEL_5_2;
- break;
- default:
- cfg->max = V4L2_MPEG_VIDEO_HEVC_LEVEL_4;
- break;
- }
+ struct mtk_vcodec_dec_dev *pdev = ctx->dev;
+
+ cfg->max = pdev->vdec_pdata->h265_params.level;
}
static void mtk_vcodec_dec_fill_h265_profile(struct v4l2_ctrl_config *cfg,
struct mtk_vcodec_dec_ctx *ctx)
{
- switch (ctx->dev->chip_model) {
- case 8188:
- case 8195:
- case 8196:
- cfg->max = V4L2_MPEG_VIDEO_HEVC_PROFILE_MAIN_10;
- break;
- default:
- cfg->max = V4L2_MPEG_VIDEO_HEVC_PROFILE_MAIN_STILL_PICTURE;
- break;
- }
+ struct mtk_vcodec_dec_dev *pdev = ctx->dev;
+
+ cfg->max = pdev->vdec_pdata->h265_params.profile;
}
static void mtk_vcodec_dec_fill_vp9_level(struct v4l2_ctrl_config *cfg,
struct mtk_vcodec_dec_ctx *ctx)
{
- switch (ctx->dev->chip_model) {
- case 8192:
- case 8188:
- cfg->max = V4L2_MPEG_VIDEO_VP9_LEVEL_5_1;
- break;
- case 8195:
- case 8196:
- cfg->max = V4L2_MPEG_VIDEO_VP9_LEVEL_5_2;
- break;
- case 8186:
- cfg->max = V4L2_MPEG_VIDEO_VP9_LEVEL_4_1;
- break;
- default:
- cfg->max = V4L2_MPEG_VIDEO_VP9_LEVEL_4_0;
- break;
- }
+ struct mtk_vcodec_dec_dev *pdev = ctx->dev;
+
+ cfg->max = pdev->vdec_pdata->vp9_params.level;
}
static void mtk_vcodec_dec_fill_vp9_profile(struct v4l2_ctrl_config *cfg,
struct mtk_vcodec_dec_ctx *ctx)
{
- switch (ctx->dev->chip_model) {
- case 8188:
- case 8195:
- case 8196:
- cfg->max = V4L2_MPEG_VIDEO_VP9_PROFILE_2;
- break;
- default:
- cfg->max = V4L2_MPEG_VIDEO_VP9_PROFILE_1;
- break;
- }
+ struct mtk_vcodec_dec_dev *pdev = ctx->dev;
+
+ cfg->max = pdev->vdec_pdata->vp9_params.profile;
}
static void mtk_vcodec_dec_reset_controls(struct v4l2_ctrl_config *cfg,
@@ -936,6 +879,18 @@ const struct mtk_vcodec_dec_pdata mtk_vdec_8183_pdata = {
.is_subdev_supported = false,
.hw_arch = MTK_VDEC_PURE_SINGLE_CORE,
.chip_model = 8183,
+ .h264_params = {
+ .level = V4L2_MPEG_VIDEO_H264_LEVEL_4_2,
+ .profile = V4L2_MPEG_VIDEO_H264_PROFILE_HIGH,
+ },
+ .h265_params = {
+ .level = V4L2_MPEG_VIDEO_HEVC_LEVEL_4,
+ .profile = V4L2_MPEG_VIDEO_HEVC_PROFILE_MAIN_STILL_PICTURE,
+ },
+ .vp9_params = {
+ .level = V4L2_MPEG_VIDEO_VP9_LEVEL_4_0,
+ .profile = V4L2_MPEG_VIDEO_VP9_PROFILE_1,
+ },
};
/* This platform data is used for one lat and one core architecture. */
@@ -975,24 +930,72 @@ const struct mtk_vcodec_dec_pdata mtk_vdec_8188_pdata = {
MTK_STATELESS_DEC_DATA,
.hw_arch = MTK_VDEC_LAT_SINGLE_CORE,
.chip_model = 8188,
+ .h264_params = {
+ .level = V4L2_MPEG_VIDEO_H264_LEVEL_5_2,
+ .profile = V4L2_MPEG_VIDEO_H264_PROFILE_HIGH_10,
+ },
+ .h265_params = {
+ .level = V4L2_MPEG_VIDEO_HEVC_LEVEL_5_1,
+ .profile = V4L2_MPEG_VIDEO_HEVC_PROFILE_MAIN_10,
+ },
+ .vp9_params = {
+ .level = V4L2_MPEG_VIDEO_VP9_LEVEL_5_1,
+ .profile = V4L2_MPEG_VIDEO_VP9_PROFILE_2,
+ },
};
const struct mtk_vcodec_dec_pdata mtk_vdec_8192_pdata = {
MTK_STATELESS_DEC_DATA,
.hw_arch = MTK_VDEC_LAT_SINGLE_CORE,
.chip_model = 8192,
+ .h264_params = {
+ .level = V4L2_MPEG_VIDEO_H264_LEVEL_5_2,
+ .profile = V4L2_MPEG_VIDEO_H264_PROFILE_HIGH,
+ },
+ .h265_params = {
+ .level = V4L2_MPEG_VIDEO_HEVC_LEVEL_4,
+ .profile = V4L2_MPEG_VIDEO_HEVC_PROFILE_MAIN_STILL_PICTURE,
+ },
+ .vp9_params = {
+ .level = V4L2_MPEG_VIDEO_VP9_LEVEL_5_1,
+ .profile = V4L2_MPEG_VIDEO_VP9_PROFILE_2,
+ },
};
const struct mtk_vcodec_dec_pdata mtk_vdec_8195_pdata = {
MTK_STATELESS_DEC_DATA,
.hw_arch = MTK_VDEC_LAT_SINGLE_CORE,
.chip_model = 8195,
+ .h264_params = {
+ .level = V4L2_MPEG_VIDEO_H264_LEVEL_6_0,
+ .profile = V4L2_MPEG_VIDEO_H264_PROFILE_HIGH_10,
+ },
+ .h265_params = {
+ .level = V4L2_MPEG_VIDEO_HEVC_LEVEL_5_2,
+ .profile = V4L2_MPEG_VIDEO_HEVC_PROFILE_MAIN_10,
+ },
+ .vp9_params = {
+ .level = V4L2_MPEG_VIDEO_VP9_LEVEL_5_1,
+ .profile = V4L2_MPEG_VIDEO_VP9_PROFILE_1,
+ },
};
const struct mtk_vcodec_dec_pdata mtk_vdec_8196_pdata = {
MTK_STATELESS_DEC_DATA,
.hw_arch = MTK_VDEC_LAT_SINGLE_CORE,
.chip_model = 8196,
+ .h264_params = {
+ .level = V4L2_MPEG_VIDEO_H264_LEVEL_6_0,
+ .profile = V4L2_MPEG_VIDEO_H264_PROFILE_HIGH_10,
+ },
+ .h265_params = {
+ .level = V4L2_MPEG_VIDEO_HEVC_LEVEL_5_2,
+ .profile = V4L2_MPEG_VIDEO_HEVC_PROFILE_MAIN_10,
+ },
+ .vp9_params = {
+ .level = V4L2_MPEG_VIDEO_VP9_LEVEL_5_2,
+ .profile = V4L2_MPEG_VIDEO_VP9_PROFILE_2,
+ },
};
const struct mtk_vcodec_dec_pdata mtk_vdec_single_core_pdata = {
@@ -1016,4 +1019,16 @@ const struct mtk_vcodec_dec_pdata mtk_vdec_8186_pdata = {
MTK_STATELESS_DEC_DATA,
.hw_arch = MTK_VDEC_PURE_SINGLE_CORE,
.chip_model = 8186,
+ .h264_params = {
+ .level = V4L2_MPEG_VIDEO_H264_LEVEL_4_2,
+ .profile = V4L2_MPEG_VIDEO_H264_PROFILE_HIGH,
+ },
+ .h265_params = {
+ .level = V4L2_MPEG_VIDEO_HEVC_LEVEL_4,
+ .profile = V4L2_MPEG_VIDEO_HEVC_PROFILE_MAIN_STILL_PICTURE,
+ },
+ .vp9_params = {
+ .level = V4L2_MPEG_VIDEO_VP9_LEVEL_4_1,
+ .profile = V4L2_MPEG_VIDEO_VP9_PROFILE_1,
+ },
};
--
2.45.2
^ permalink raw reply related
* [PATCH v9 0/9] Enable video decoder & encoder for MT8189
From: Kyrie Wu @ 2026-04-24 3:05 UTC (permalink / raw)
To: Tiffany Lin, Andrew-CT Chen, Yunfei Dong, Mauro Carvalho Chehab,
Rob Herring, Krzysztof Kozlowski, Conor Dooley, Matthias Brugger,
AngeloGioacchino Del Regno, Kyrie Wu, Hans Verkuil,
Nicolas Dufresne, Nathan Hebert, Arnd Bergmann, Irui Wang,
George Sun, linux-media, devicetree, linux-kernel,
linux-arm-kernel, linux-mediatek
Cc: Neil Armstrong, Andrzej Pietrasiewicz, Yilong Zhou
This series have the follow changing:
Firstly add mt8189 video decoder compatible, profile and level to support
MT8189 kernel driver.
Secondly fix some bugs, including vp 4K profile2 and media device node
number bug.
Lastly, add mt8189 video encoder compatible.
This series has been tested with MT8189 tast test.
Encoding and decoding worked for this chip.
Patches 1 Add decoder compatible.
Patches 1 fix decoder chip model.
Patches 3-4 Add profile, level and probability size supporting.
Patches 6 add decoder platform data to support MT8189.
Patches 5 & 7 fix some bugs.
Patches 8-9 Adds encoder compatible.
---
H264 test results:
./fluster.py run -d GStreamer-H.264-V4L2SL-Gst1.0 -j2 -t 90
JVT-AVC_V1 Ran 96/135 tests successfully
VP9 test results:
./fluster.py run -d GStreamer-VP9-V4L2SL-Gst1.0 -j2 -t 90
VP9-TEST-VECTORS Ran 276/305 tests successfully
v4l2-compliance test results:
Compliance test for mtk-vcodec-enc device /dev/video2:
Total for mtk-vcodec-enc device /dev/video2: 47, Succeeded: 46, Failed: 1, Warnings: 0
Compliance test for mtk-vcodec-dec device /dev/video3:
Total for mtk-vcodec-dec device /dev/video3: 48, Succeeded: 48, Failed: 0, Warnings: 0
scp upstream link:
https://patchwork.kernel.org/project/linux-mediatek/patch/20250811015922.32680-1-huayu.zong@mediatek.com/
dtsi upstream link:
https://lore.kernel.org/linux-mediatek/20251030134541.784011-12-jh.hsu@mediatek.com/T/#m847e35de0a5b18fac0ca0624a8559d84964ad5c7
Changes compared with v8:
--Rebased on top of the latest media tree
Changes compared with v7:
--relocate the patches set
--refactor decoder platform data patch
--fix commit message errors
Changes compared with v6:
--refactor the patches of set compatible data, profile and level
--add reviewer to commit messages
--fix commit message errors
Changes compared with v5:
--refactor the patches of set compatible data, profile and level
--add reviewer to commit messages
--fix commit message errors
Changes compared with v4:
--update H264 & vp9 fluster test results
--update vp9 single core decoder prob size setting and commit messages
Changes compared with v3:
--add reviewer to commit messages
--Rebased on top of the latest media tree
Changes compared with v2:
--add H264 fluster test results
--reorder compatible string for dt-bindings
Changes compared with v1:
--add v4l2-compliance test results
--add scp upstream link
--add HW difference discriptions for dt-bindings commit messages
This series patches dependent on:
[1]
https://patchwork.linuxtv.org/project/linux-media/patch/20260328051630.7937-2-yunfei.dong@mediatek.com/
[2]
https://patchwork.linuxtv.org/project/linux-media/patch/20260423073345.27402-2-irui.wang@mediatek.com/
Kyrie Wu (9):
dt-bindings: media: mediatek: decoder: Add MT8189
mediatek,vcodec-decoder
media: mediatek: decoder: Add a new platform data member
media: mediatek: vcodec: Refactor Decoder profile & level Handling
media: mediatek: vcodec: Add VP9 Probability Size Configuration
media: mediatek: vcodec: Fix vp9 4096x2176 fail for profile2
media: mediatek: vcodec: add decoder compatible to support MT8189
media: mediatek: vcodec: Fix media device node number
dt-bindings: media: Add MT8189 mediatek,vcodec-encoder
media: mediatek: encoder: Add MT8189 encoder compatible data
.../media/mediatek,vcodec-encoder.yaml | 2 +
.../media/mediatek,vcodec-subdev-decoder.yaml | 5 +-
.../mediatek/vcodec/decoder/mtk_vcodec_dec.c | 2 +-
.../mediatek/vcodec/decoder/mtk_vcodec_dec.h | 6 +
.../vcodec/decoder/mtk_vcodec_dec_drv.c | 46 ++--
.../vcodec/decoder/mtk_vcodec_dec_drv.h | 35 ++-
.../vcodec/decoder/mtk_vcodec_dec_hw.c | 2 +-
.../vcodec/decoder/mtk_vcodec_dec_stateful.c | 14 +
.../vcodec/decoder/mtk_vcodec_dec_stateless.c | 239 ++++++++++++------
.../vcodec/decoder/vdec/vdec_vp9_req_lat_if.c | 14 +-
.../vcodec/encoder/mtk_vcodec_enc_drv.c | 14 +
11 files changed, 253 insertions(+), 126 deletions(-)
--
2.45.2
^ permalink raw reply
* Re: [PATCH v3 02/11] iommu: Pass in reset result to pci_dev_reset_iommu_done()
From: Baolu Lu @ 2026-04-24 2:56 UTC (permalink / raw)
To: Nicolin Chen
Cc: Will Deacon, Robin Murphy, Joerg Roedel, Bjorn Helgaas,
Jason Gunthorpe, Rafael J . Wysocki, Len Brown,
Pranjal Shrivastava, Mostafa Saleh, Kevin Tian, linux-arm-kernel,
iommu, linux-kernel, linux-acpi, linux-pci, vsethi, Shuai Xue
In-Reply-To: <aerZa3aQBMCwzzT8@Asurada-Nvidia>
On 4/24/26 10:46, Nicolin Chen wrote:
> On Fri, Apr 24, 2026 at 10:38:09AM +0800, Baolu Lu wrote:
>> On 4/17/26 07:28, Nicolin Chen wrote:
>>> @@ -4083,6 +4093,18 @@ void pci_dev_reset_iommu_done(struct pci_dev *pdev)
>>> if (WARN_ON(!group->blocking_domain))
>>> return;
>>> + /*
>>> + * A reset failure implies that the device might be unreliable. E.g. its
>>> + * device cache might retain stale entries, which potentially results in
>>> + * memory corruption. Thus, do not unblock the device until a successful
>>> + * reset.
>>> + */
>>> + if (!reset_succeeds) {
>>> + pci_err(pdev,
>>> + "Reset failed. Keep it blocked to protect memory\n");
>>> + return;
>>> + }
>>
>> Nit: pci_dev_reset_iommu_done() does nothing if reset_succeeds is false.
>> Would it be better to handle this in the caller instead? Something like:
>>
>> if (reset_succeeds)
>> pci_dev_reset_iommu_done(dev);
>>
>> ?
>
> It would also need a print and some duplicated comments. Actually,
> that would be my v2, which Kevin suggested this against:
> https://lore.kernel.org/all/BN9PR11MB5276706AE4E0BBE86F0F6E158C4EA@BN9PR11MB5276.namprd11.prod.outlook.com/
Oh, I forgot that comment.
> Though I don't have a strong personal reference here, I do see this
> version slightly cleaner than doing in the callers.
Okay, you own the decision.
> Thanks
> Nicolin
Thanks,
baolu
^ permalink raw reply
* [PATCH v1 3/3] PCI: imx6: Add root port reset to support link recovery
From: Richard Zhu @ 2026-04-24 2:57 UTC (permalink / raw)
To: robh, krzk+dt, conor+dt, bhelgaas, frank.li, l.stach, lpieralisi,
kwilczynski, mani, s.hauer, kernel, festevam
Cc: linux-pci, linux-arm-kernel, devicetree, imx, linux-kernel,
Richard Zhu
In-Reply-To: <20260424025735.1490772-1-hongxing.zhu@nxp.com>
The PCIe link can go down due to various unexpected circumstances. Add
root port reset support to enable link recovery for the i.MX PCIe
controller when the optional "intr" interrupt is present.
Reset root port to uninitialize, initialize the PCIe controller, and
restart the PCIe link at end when a link down event happens.
On i.MX95 platforms, link events and PME share the same interrupt line.
The link event interrupt cannot use a threaded-only IRQ handler because
the PME driver uses request_irq() with only the IRQF_SHARED flag set,
which requires a primary handler.
To handle this shared interrupt scenario, register a primary interrupt
handler with IRQF_SHARED for link events and manipulate the link event
enable bits to ensure the shared interrupt source triggers only one
handler at a time.
Signed-off-by: Richard Zhu <hongxing.zhu@nxp.com>
---
drivers/pci/controller/dwc/pci-imx6.c | 122 ++++++++++++++++++++++++++
1 file changed, 122 insertions(+)
diff --git a/drivers/pci/controller/dwc/pci-imx6.c b/drivers/pci/controller/dwc/pci-imx6.c
index e35044cc52185..0fb75d4b4e636 100644
--- a/drivers/pci/controller/dwc/pci-imx6.c
+++ b/drivers/pci/controller/dwc/pci-imx6.c
@@ -34,6 +34,7 @@
#include <linux/pm_runtime.h>
#include "../../pci.h"
+#include "../pci-host-common.h"
#include "pcie-designware.h"
#define IMX8MQ_GPR_PCIE_REF_USE_PAD BIT(9)
@@ -78,6 +79,10 @@
#define IMX95_SID_MASK GENMASK(5, 0)
#define IMX95_MAX_LUT 32
+#define IMX95_LINK_INT_CTRL_STS 0x1040
+#define IMX95_LINK_DOWN_INT_STS BIT(11)
+#define IMX95_LINK_DOWN_INT_EN BIT(10)
+
#define IMX95_PCIE_RST_CTRL 0x3010
#define IMX95_PCIE_COLD_RST BIT(0)
@@ -125,6 +130,8 @@ enum imx_pcie_variants {
#define IMX_PCIE_MAX_INSTANCES 2
struct imx_pcie;
+static int imx_pcie_reset_root_port(struct pci_host_bridge *bridge,
+ struct pci_dev *pdev);
struct imx_pcie_drvdata {
enum imx_pcie_variants variant;
@@ -158,6 +165,7 @@ struct imx_pcie {
bool supports_clkreq;
bool enable_ext_refclk;
struct regmap *iomuxc_gpr;
+ u32 lnk_intr;
u16 msi_ctrl;
u32 controller_id;
struct reset_control *pciephy_reset;
@@ -1306,6 +1314,13 @@ static int imx_pcie_host_init(struct dw_pcie_rp *pp)
imx_setup_phy_mpll(imx_pcie);
+ /*
+ * Callback invoked by PCI core when link down is detected and
+ * recovery is needed.
+ */
+ if (pp->bridge)
+ pp->bridge->reset_root_port = imx_pcie_reset_root_port;
+
return 0;
err_phy_off:
@@ -1573,6 +1588,9 @@ static int imx_pcie_suspend_noirq(struct device *dev)
if (!(imx_pcie->drvdata->flags & IMX_PCIE_FLAG_SUPPORTS_SUSPEND))
return 0;
+ if (imx_pcie->lnk_intr)
+ regmap_clear_bits(imx_pcie->iomuxc_gpr, IMX95_LINK_INT_CTRL_STS,
+ IMX95_LINK_DOWN_INT_EN);
imx_pcie_msi_save_restore(imx_pcie, true);
if (imx_check_flag(imx_pcie, IMX_PCIE_FLAG_HAS_LUT))
imx_pcie_lut_save(imx_pcie);
@@ -1623,6 +1641,9 @@ static int imx_pcie_resume_noirq(struct device *dev)
if (imx_check_flag(imx_pcie, IMX_PCIE_FLAG_HAS_LUT))
imx_pcie_lut_restore(imx_pcie);
imx_pcie_msi_save_restore(imx_pcie, false);
+ if (imx_pcie->lnk_intr)
+ regmap_set_bits(imx_pcie->iomuxc_gpr, IMX95_LINK_INT_CTRL_STS,
+ IMX95_LINK_DOWN_INT_EN);
return 0;
}
@@ -1632,6 +1653,84 @@ static const struct dev_pm_ops imx_pcie_pm_ops = {
imx_pcie_resume_noirq)
};
+static irqreturn_t imx_pcie_link_irq_handler(int irq, void *priv)
+{
+ struct imx_pcie *imx_pcie = priv;
+ struct dw_pcie *pci = imx_pcie->pci;
+ struct device *dev = pci->dev;
+ u32 val;
+
+ regmap_read(imx_pcie->iomuxc_gpr, IMX95_LINK_INT_CTRL_STS, &val);
+ if (val & IMX95_LINK_DOWN_INT_STS) {
+ dev_dbg(dev, "PCIe link down detected, initiating recovery\n");
+ regmap_clear_bits(imx_pcie->iomuxc_gpr, IMX95_LINK_INT_CTRL_STS,
+ IMX95_LINK_DOWN_INT_EN);
+ regmap_set_bits(imx_pcie->iomuxc_gpr, IMX95_LINK_INT_CTRL_STS,
+ IMX95_LINK_DOWN_INT_STS);
+
+ return IRQ_WAKE_THREAD;
+ } else {
+ return IRQ_NONE;
+ }
+}
+
+static irqreturn_t imx_pcie_link_irq_thread(int irq, void *priv)
+{
+ struct imx_pcie *imx_pcie = priv;
+ struct dw_pcie *pci = imx_pcie->pci;
+ struct dw_pcie_rp *pp = &pci->pp;
+ struct pci_dev *port;
+
+ for_each_pci_bridge(port, pp->bridge->bus)
+ if (pci_pcie_type(port) == PCI_EXP_TYPE_ROOT_PORT)
+ pci_host_handle_link_down(port);
+
+ regmap_set_bits(imx_pcie->iomuxc_gpr, IMX95_LINK_INT_CTRL_STS,
+ IMX95_LINK_DOWN_INT_EN);
+
+ return IRQ_HANDLED;
+}
+
+static int imx_pcie_reset_root_port(struct pci_host_bridge *bridge,
+ struct pci_dev *pdev)
+{
+ struct pci_bus *bus = bridge->bus;
+ struct dw_pcie_rp *pp = bus->sysdata;
+ struct dw_pcie *pci = to_dw_pcie_from_pp(pp);
+ struct imx_pcie *imx_pcie = to_imx_pcie(pci);
+ int ret;
+
+ imx_pcie_msi_save_restore(imx_pcie, true);
+ if (imx_check_flag(imx_pcie, IMX_PCIE_FLAG_HAS_LUT))
+ imx_pcie_lut_save(imx_pcie);
+ imx_pcie_stop_link(pci);
+ imx_pcie_host_exit(pp);
+
+ ret = imx_pcie_host_init(pp);
+ if (ret) {
+ dev_err(pci->dev, "Failed to re-init PCIe\n");
+ return ret;
+ }
+ ret = dw_pcie_setup_rc(pp);
+ if (ret)
+ goto err_host_deinit;
+
+ imx_pcie_start_link(pci);
+ dw_pcie_wait_for_link(pci);
+
+ if (imx_check_flag(imx_pcie, IMX_PCIE_FLAG_HAS_LUT))
+ imx_pcie_lut_restore(imx_pcie);
+ imx_pcie_msi_save_restore(imx_pcie, false);
+
+ dev_dbg(pci->dev, "Root port reset completed\n");
+ return 0;
+
+err_host_deinit:
+ imx_pcie_host_exit(pp);
+
+ return ret;
+}
+
static int imx_pcie_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
@@ -1834,9 +1933,32 @@ static int imx_pcie_probe(struct platform_device *pdev)
val |= PCI_MSI_FLAGS_ENABLE;
dw_pcie_writew_dbi(pci, offset + PCI_MSI_FLAGS, val);
}
+
+ /* Get link event irq if it is present */
+ imx_pcie->lnk_intr = platform_get_irq_byname(pdev, "intr");
+ if (imx_pcie->lnk_intr < 0)
+ return 0;
+
+ ret = devm_request_threaded_irq(dev, imx_pcie->lnk_intr,
+ imx_pcie_link_irq_handler,
+ imx_pcie_link_irq_thread,
+ IRQF_SHARED,
+ "lnk", imx_pcie);
+ if (ret) {
+ dev_err_probe(dev, ret, "Unable to request LNK IRQ\n");
+ goto err_host_deinit;
+ }
+
+ regmap_set_bits(imx_pcie->iomuxc_gpr, IMX95_LINK_INT_CTRL_STS,
+ IMX95_LINK_DOWN_INT_EN);
}
return 0;
+
+err_host_deinit:
+ dw_pcie_host_deinit(&pci->pp);
+
+ return ret;
}
static void imx_pcie_shutdown(struct platform_device *pdev)
--
2.37.1
^ permalink raw reply related
* [PATCH v1 2/3] arm64: dts: imx95: Add dma, intr, aer and pme interrupters for pcie{0,1}
From: Richard Zhu @ 2026-04-24 2:57 UTC (permalink / raw)
To: robh, krzk+dt, conor+dt, bhelgaas, frank.li, l.stach, lpieralisi,
kwilczynski, mani, s.hauer, kernel, festevam
Cc: linux-pci, linux-arm-kernel, devicetree, imx, linux-kernel,
Richard Zhu
In-Reply-To: <20260424025735.1490772-1-hongxing.zhu@nxp.com>
Add dma, intr, aer and pme interrupters for pcie{0,1}.
Signed-off-by: Richard Zhu <hongxing.zhu@nxp.com>
---
arch/arm64/boot/dts/freescale/imx95.dtsi | 16 ++++++++++++----
1 file changed, 12 insertions(+), 4 deletions(-)
diff --git a/arch/arm64/boot/dts/freescale/imx95.dtsi b/arch/arm64/boot/dts/freescale/imx95.dtsi
index 71394871d8dd0..6896d9c15bf53 100644
--- a/arch/arm64/boot/dts/freescale/imx95.dtsi
+++ b/arch/arm64/boot/dts/freescale/imx95.dtsi
@@ -1861,8 +1861,12 @@ pcie0: pcie@4c300000 {
bus-range = <0x00 0xff>;
num-lanes = <1>;
num-viewport = <8>;
- interrupts = <GIC_SPI 310 IRQ_TYPE_LEVEL_HIGH>;
- interrupt-names = "msi";
+ interrupts = <GIC_SPI 310 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 311 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 310 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 310 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 310 IRQ_TYPE_LEVEL_HIGH>;
+ interrupt-names = "msi", "dma", "intr", "aer", "pme";
#interrupt-cells = <1>;
interrupt-map-mask = <0 0 0 0x7>;
interrupt-map = <0 0 0 1 &gic 0 0 GIC_SPI 306 IRQ_TYPE_LEVEL_HIGH>,
@@ -1936,8 +1940,12 @@ pcie1: pcie@4c380000 {
bus-range = <0x00 0xff>;
num-lanes = <1>;
num-viewport = <8>;
- interrupts = <GIC_SPI 316 IRQ_TYPE_LEVEL_HIGH>;
- interrupt-names = "msi";
+ interrupts = <GIC_SPI 316 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 317 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 316 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 316 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 316 IRQ_TYPE_LEVEL_HIGH>;
+ interrupt-names = "msi", "dma", "intr", "aer", "pme";
#interrupt-cells = <1>;
interrupt-map-mask = <0 0 0 0x7>;
interrupt-map = <0 0 0 1 &gic 0 0 GIC_SPI 312 IRQ_TYPE_LEVEL_HIGH>,
--
2.37.1
^ permalink raw reply related
* [PATCH v1 1/3] dt-bindings: PCI: imx6q-pcie: Add intr, aer and pme interrupts
From: Richard Zhu @ 2026-04-24 2:57 UTC (permalink / raw)
To: robh, krzk+dt, conor+dt, bhelgaas, frank.li, l.stach, lpieralisi,
kwilczynski, mani, s.hauer, kernel, festevam
Cc: linux-pci, linux-arm-kernel, devicetree, imx, linux-kernel,
Richard Zhu
In-Reply-To: <20260424025735.1490772-1-hongxing.zhu@nxp.com>
Add optional 'intr', 'aer', and 'pme' interrupt entries to the i.MX6Q
PCIe binding to support PCIe event-based interrupts for general
controller events, Advanced Error Reporting, and Power Management Events
respectively.
Signed-off-by: Richard Zhu <hongxing.zhu@nxp.com>
---
Documentation/devicetree/bindings/pci/fsl,imx6q-pcie.yaml | 6 ++++++
1 file changed, 6 insertions(+)
diff --git a/Documentation/devicetree/bindings/pci/fsl,imx6q-pcie.yaml b/Documentation/devicetree/bindings/pci/fsl,imx6q-pcie.yaml
index 9d1349855b422..badc7fcbd556c 100644
--- a/Documentation/devicetree/bindings/pci/fsl,imx6q-pcie.yaml
+++ b/Documentation/devicetree/bindings/pci/fsl,imx6q-pcie.yaml
@@ -58,12 +58,18 @@ properties:
items:
- description: builtin MSI controller.
- description: builtin DMA controller.
+ - description: PCIe event interrupt.
+ - description: builtin AER SPI standalone interrupter line.
+ - description: builtin PME SPI standalone interrupter line.
interrupt-names:
minItems: 1
items:
- const: msi
- const: dma
+ - const: intr
+ - const: aer
+ - const: pme
reset-gpio:
description: Should specify the GPIO for controlling the PCI bus device
--
2.37.1
^ permalink raw reply related
* [PATCH v1 0/3] Add root port reset to support link recovery
From: Richard Zhu @ 2026-04-24 2:57 UTC (permalink / raw)
To: robh, krzk+dt, conor+dt, bhelgaas, frank.li, l.stach, lpieralisi,
kwilczynski, mani, s.hauer, kernel, festevam
Cc: linux-pci, linux-arm-kernel, devicetree, imx, linux-kernel
Based on the following patch-set[1] issued by Mani.
Add support for resetting the Root Port for i.MX PCIe to enable link recovery.
[1] https://patchwork.kernel.org/project/linux-pci/cover/20260310-pci-port-reset-v7-0-9dd00ccc25ab@oss.qualcomm.com/
PCIe links can go down due to various unexpected circumstances. This patch series
adds root port reset support for link recovery on i.MX PCIe controllers when the
optional "intr" interrupt is present.
When a link down event is detected, the root port reset uninitializes and
reinitializes the PCIe controller, then restarts the PCIe link.
On i.MX95 platforms, link events and PME share the same interrupt line.
Link event interrupts cannot use only an IRQ thread handler because the PME
driver uses request_irq() to bind the PME interrupt directly with only the
IRQF_SHARED flag set.
To address this, we register one handler with IRQF_SHARED for link event
interrupts and manipulate the enable bits of link events to ensure the same
interrupt source is triggered only once at a time.
Additionally, this series adds 'intr', 'aer', and 'pme' interrupt entries to
the i.MX6Q PCIe binding to support PCIe event-based interrupts for general
controller events, Advanced Error Reporting, and Power Management Events
respectively.
[PATCH v1 1/3] dt-bindings: PCI: imx6q-pcie: Add intr, aer and pme
[PATCH v1 2/3] arm64: dts: imx95: Add dma, intr, aer and pme
[PATCH v1 3/3] PCI: imx6: Add root port reset to support link
Documentation/devicetree/bindings/pci/fsl,imx6q-pcie.yaml | 6 +++++
arch/arm64/boot/dts/freescale/imx95.dtsi | 16 +++++++++---
drivers/pci/controller/dwc/pci-imx6.c | 122 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
3 files changed, 140 insertions(+), 4 deletions(-)
^ permalink raw reply
* Re: [PATCH v3 05/11] iommu: Change group->devices to RCU-protected list
From: Baolu Lu @ 2026-04-24 2:53 UTC (permalink / raw)
To: Nicolin Chen, Will Deacon, Robin Murphy, Joerg Roedel,
Bjorn Helgaas, Jason Gunthorpe
Cc: Rafael J . Wysocki, Len Brown, Pranjal Shrivastava, Mostafa Saleh,
Kevin Tian, linux-arm-kernel, iommu, linux-kernel, linux-acpi,
linux-pci, vsethi, Shuai Xue
In-Reply-To: <12a224061de4fff9e0725909fd0ba4e14996ff08.1776381841.git.nicolinc@nvidia.com>
On 4/17/26 07:28, Nicolin Chen wrote:
> To allow lockless iterations of the group->devices list in an ISR context
> that cannot hold the group->mutex, change the list to be RCU protected.
>
> Signed-off-by: Nicolin Chen<nicolinc@nvidia.com>
> ---
> drivers/iommu/iommu.c | 16 +++++++++-------
> 1 file changed, 9 insertions(+), 7 deletions(-)
>
> diff --git a/drivers/iommu/iommu.c b/drivers/iommu/iommu.c
> index 768ac728b4cc3..d1be62a07904a 100644
> --- a/drivers/iommu/iommu.c
> +++ b/drivers/iommu/iommu.c
> @@ -84,18 +84,20 @@ struct group_device {
> */
> bool blocked;
> unsigned int reset_depth;
> + struct rcu_head rcu;
> };
>
> /* Iterate over each struct group_device in a struct iommu_group */
> #define for_each_group_device(group, pos) \
> - list_for_each_entry(pos, &(group)->devices, list)
> + list_for_each_entry_rcu(pos, &(group)->devices, list, \
> + lockdep_is_held(&(group)->mutex))
for_each_group_device() is used in bus_iommu_probe() without holding
either the mutex or the rcu lock:
static int bus_iommu_probe(const struct bus_type *bus)
{
struct iommu_group *group, *next;
LIST_HEAD(group_list);
int ret;
[-- cut for short --]
mutex_unlock(&group->mutex);
/*
* FIXME: Mis-locked because the ops->probe_finalize()
call-back
* of some IOMMU drivers calls arm_iommu_attach_device() which
* in-turn might call back into IOMMU core code, where it tries
* to take group->mutex, resulting in a deadlock.
*/
for_each_group_device(group, gdev)
iommu_group_do_probe_finalize(gdev->dev);
}
return 0;
}
Will the change above trigger a lockdep splat due to this "mis-locked"
case?"
Thanks,
baolu
^ permalink raw reply
* [PATCH v3 9/9] ARM: dts: mediatek: mt7623n-bananapi-bpi-r2: add HDMI audio machine node
From: Daniel Golle @ 2026-04-24 2:50 UTC (permalink / raw)
To: Liam Girdwood, Mark Brown, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Matthias Brugger, AngeloGioacchino Del Regno,
Jaroslav Kysela, Takashi Iwai, Cyril Chao, Arnd Bergmann,
Nícolas F. R. A. Prado, Kuninori Morimoto, Daniel Golle,
Eugen Hristev, linux-sound, devicetree, linux-kernel,
linux-arm-kernel, linux-mediatek
In-Reply-To: <cover.1776998727.git.daniel@makrotopia.org>
Instantiate the mediatek,mt2701-hdmi-audio machine on the
BananaPi BPI-R2, binding the AFE HDMI playback path to the
on-chip HDMI transmitter acting as the generic HDMI codec.
Signed-off-by: Daniel Golle <daniel@makrotopia.org>
---
v3: no changes
v2: no changes
arch/arm/boot/dts/mediatek/mt7623n-bananapi-bpi-r2.dts | 7 +++++++
1 file changed, 7 insertions(+)
diff --git a/arch/arm/boot/dts/mediatek/mt7623n-bananapi-bpi-r2.dts b/arch/arm/boot/dts/mediatek/mt7623n-bananapi-bpi-r2.dts
index a37f3fa223c7..139a76764faa 100644
--- a/arch/arm/boot/dts/mediatek/mt7623n-bananapi-bpi-r2.dts
+++ b/arch/arm/boot/dts/mediatek/mt7623n-bananapi-bpi-r2.dts
@@ -132,6 +132,13 @@ memory@80000000 {
device_type = "memory";
reg = <0 0x80000000 0 0x80000000>;
};
+
+ sound-hdmi {
+ compatible = "mediatek,mt7623n-hdmi-audio",
+ "mediatek,mt2701-hdmi-audio";
+ mediatek,platform = <&afe>;
+ mediatek,audio-codec = <&hdmi0>;
+ };
};
&bls {
--
2.54.0
^ permalink raw reply related
* [PATCH v3 8/9] ARM: dts: mediatek: mt7623: wire HDMI audio path clocks into AFE
From: Daniel Golle @ 2026-04-24 2:50 UTC (permalink / raw)
To: Liam Girdwood, Mark Brown, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Matthias Brugger, AngeloGioacchino Del Regno,
Jaroslav Kysela, Takashi Iwai, Cyril Chao, Arnd Bergmann,
Nícolas F. R. A. Prado, Kuninori Morimoto, Daniel Golle,
Eugen Hristev, linux-sound, devicetree, linux-kernel,
linux-arm-kernel, linux-mediatek
In-Reply-To: <cover.1776998727.git.daniel@makrotopia.org>
Mirror the MT2701 change for the MT7623 SoC dtsi: add HADDS2PLL,
audio_hdmi, audio_spdf and audio_apll to the AFE clocks list and
reparent the AUDPLL mux to HADDS2PLL_98M. Required for HDMI audio
on MT7623N boards via the shared mt2701 AFE driver.
Signed-off-by: Daniel Golle <daniel@makrotopia.org>
---
v3: no changes
v2: no changes
arch/arm/boot/dts/mediatek/mt7623.dtsi | 21 ++++++++++++++++-----
1 file changed, 16 insertions(+), 5 deletions(-)
diff --git a/arch/arm/boot/dts/mediatek/mt7623.dtsi b/arch/arm/boot/dts/mediatek/mt7623.dtsi
index 71ac2b94c6ba..4eb028ffee6f 100644
--- a/arch/arm/boot/dts/mediatek/mt7623.dtsi
+++ b/arch/arm/boot/dts/mediatek/mt7623.dtsi
@@ -665,7 +665,11 @@ afe: audio-controller {
<&audsys CLK_AUD_AFE_CONN>,
<&audsys CLK_AUD_A1SYS>,
<&audsys CLK_AUD_A2SYS>,
- <&audsys CLK_AUD_AFE_MRGIF>;
+ <&audsys CLK_AUD_AFE_MRGIF>,
+ <&topckgen CLK_TOP_HADDS2PLL_294M>,
+ <&audsys CLK_AUD_HDMI>,
+ <&audsys CLK_AUD_SPDF>,
+ <&audsys CLK_AUD_APLL>;
clock-names = "infra_sys_audio_clk",
"top_audio_mux1_sel",
@@ -700,15 +704,22 @@ afe: audio-controller {
"audio_afe_conn_pd",
"audio_a1sys_pd",
"audio_a2sys_pd",
- "audio_mrgif_pd";
+ "audio_mrgif_pd",
+ "hadds2pll_294m",
+ "audio_hdmi_pd",
+ "audio_spdf_pd",
+ "audio_apll_pd";
assigned-clocks = <&topckgen CLK_TOP_AUD_MUX1_SEL>,
<&topckgen CLK_TOP_AUD_MUX2_SEL>,
<&topckgen CLK_TOP_AUD_MUX1_DIV>,
- <&topckgen CLK_TOP_AUD_MUX2_DIV>;
+ <&topckgen CLK_TOP_AUD_MUX2_DIV>,
+ <&topckgen CLK_TOP_AUDPLL_MUX_SEL>;
assigned-clock-parents = <&topckgen CLK_TOP_AUD1PLL_98M>,
- <&topckgen CLK_TOP_AUD2PLL_90M>;
- assigned-clock-rates = <0>, <0>, <49152000>, <45158400>;
+ <&topckgen CLK_TOP_AUD2PLL_90M>,
+ <0>, <0>,
+ <&topckgen CLK_TOP_HADDS2PLL_98M>;
+ assigned-clock-rates = <0>, <0>, <49152000>, <45158400>, <0>;
};
};
--
2.54.0
^ permalink raw reply related
* [PATCH v3 7/9] ARM: dts: mediatek: mt2701: wire HDMI audio path clocks into AFE
From: Daniel Golle @ 2026-04-24 2:50 UTC (permalink / raw)
To: Liam Girdwood, Mark Brown, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Matthias Brugger, AngeloGioacchino Del Regno,
Jaroslav Kysela, Takashi Iwai, Cyril Chao, Arnd Bergmann,
Nícolas F. R. A. Prado, Kuninori Morimoto, Daniel Golle,
Eugen Hristev, linux-sound, devicetree, linux-kernel,
linux-arm-kernel, linux-mediatek
In-Reply-To: <cover.1776998727.git.daniel@makrotopia.org>
Add the HADDS2 PLL 294 MHz root, the audio_hdmi and audio_spdf
interface gates and the audio_apll gate to the MT2701 AFE node,
and reparent the AUDPLL mux to HADDS2PLL_98M so the HDMI audio
serial clock path has a stable 294.912 MHz source. The clock
names match the updated mediatek,mt2701-audio binding.
Signed-off-by: Daniel Golle <daniel@makrotopia.org>
---
v3: no changes
v2: no changes
arch/arm/boot/dts/mediatek/mt2701.dtsi | 21 ++++++++++++++++-----
1 file changed, 16 insertions(+), 5 deletions(-)
diff --git a/arch/arm/boot/dts/mediatek/mt2701.dtsi b/arch/arm/boot/dts/mediatek/mt2701.dtsi
index 128b87229f3d..80c8c7e6a422 100644
--- a/arch/arm/boot/dts/mediatek/mt2701.dtsi
+++ b/arch/arm/boot/dts/mediatek/mt2701.dtsi
@@ -464,7 +464,11 @@ afe: audio-controller {
<&audsys CLK_AUD_AFE_CONN>,
<&audsys CLK_AUD_A1SYS>,
<&audsys CLK_AUD_A2SYS>,
- <&audsys CLK_AUD_AFE_MRGIF>;
+ <&audsys CLK_AUD_AFE_MRGIF>,
+ <&topckgen CLK_TOP_HADDS2PLL_294M>,
+ <&audsys CLK_AUD_HDMI>,
+ <&audsys CLK_AUD_SPDF>,
+ <&audsys CLK_AUD_APLL>;
clock-names = "infra_sys_audio_clk",
"top_audio_mux1_sel",
@@ -499,15 +503,22 @@ afe: audio-controller {
"audio_afe_conn_pd",
"audio_a1sys_pd",
"audio_a2sys_pd",
- "audio_mrgif_pd";
+ "audio_mrgif_pd",
+ "hadds2pll_294m",
+ "audio_hdmi_pd",
+ "audio_spdf_pd",
+ "audio_apll_pd";
assigned-clocks = <&topckgen CLK_TOP_AUD_MUX1_SEL>,
<&topckgen CLK_TOP_AUD_MUX2_SEL>,
<&topckgen CLK_TOP_AUD_MUX1_DIV>,
- <&topckgen CLK_TOP_AUD_MUX2_DIV>;
+ <&topckgen CLK_TOP_AUD_MUX2_DIV>,
+ <&topckgen CLK_TOP_AUDPLL_MUX_SEL>;
assigned-clock-parents = <&topckgen CLK_TOP_AUD1PLL_98M>,
- <&topckgen CLK_TOP_AUD2PLL_90M>;
- assigned-clock-rates = <0>, <0>, <49152000>, <45158400>;
+ <&topckgen CLK_TOP_AUD2PLL_90M>,
+ <0>, <0>,
+ <&topckgen CLK_TOP_HADDS2PLL_98M>;
+ assigned-clock-rates = <0>, <0>, <49152000>, <45158400>, <0>;
};
};
--
2.54.0
^ permalink raw reply related
* [PATCH v3 6/9] ASoC: mediatek: mt2701: add machine driver for on-chip HDMI codec
From: Daniel Golle @ 2026-04-24 2:50 UTC (permalink / raw)
To: Liam Girdwood, Mark Brown, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Matthias Brugger, AngeloGioacchino Del Regno,
Jaroslav Kysela, Takashi Iwai, Cyril Chao, Arnd Bergmann,
Nícolas F. R. A. Prado, Kuninori Morimoto, Daniel Golle,
Eugen Hristev, linux-sound, devicetree, linux-kernel,
linux-arm-kernel, linux-mediatek
In-Reply-To: <cover.1776998727.git.daniel@makrotopia.org>
Add a simple ASoC machine driver that wires the MT2701/MT7623N
AFE HDMI playback path to the on-chip HDMI transmitter exposed
as a generic hdmi-audio-codec "i2s-hifi" DAI.
The driver binds to "mediatek,mt2701-hdmi-audio". MT7623N device
trees carry "mediatek,mt7623n-hdmi-audio" as a board-specific
fallback, matching the dt-binding.
Signed-off-by: Daniel Golle <daniel@makrotopia.org>
---
v3: no changes
v2: no changes
sound/soc/mediatek/Kconfig | 10 +++
sound/soc/mediatek/mt2701/Makefile | 1 +
sound/soc/mediatek/mt2701/mt2701-hdmi.c | 114 ++++++++++++++++++++++++
3 files changed, 125 insertions(+)
create mode 100644 sound/soc/mediatek/mt2701/mt2701-hdmi.c
diff --git a/sound/soc/mediatek/Kconfig b/sound/soc/mediatek/Kconfig
index 3a1e1fa3fe5c..fa076e7854ad 100644
--- a/sound/soc/mediatek/Kconfig
+++ b/sound/soc/mediatek/Kconfig
@@ -26,6 +26,16 @@ config SND_SOC_MT2701_CS42448
Select Y if you have such device.
If unsure select "N".
+config SND_SOC_MT2701_HDMI
+ tristate "ASoC Audio driver for MT2701 with on-chip HDMI codec"
+ depends on SND_SOC_MT2701
+ select SND_SOC_HDMI_CODEC
+ help
+ This adds the ASoC machine driver for MediaTek MT2701 and
+ MT7623N boards routing the AFE I2S back-end to the on-chip
+ HDMI transmitter via the generic HDMI codec.
+ If unsure select "N".
+
config SND_SOC_MT2701_WM8960
tristate "ASoc Audio driver for MT2701 with WM8960 codec"
depends on SND_SOC_MT2701 && I2C
diff --git a/sound/soc/mediatek/mt2701/Makefile b/sound/soc/mediatek/mt2701/Makefile
index 507fa26c3945..59623d3d3a03 100644
--- a/sound/soc/mediatek/mt2701/Makefile
+++ b/sound/soc/mediatek/mt2701/Makefile
@@ -5,4 +5,5 @@ obj-$(CONFIG_SND_SOC_MT2701) += snd-soc-mt2701-afe.o
# machine driver
obj-$(CONFIG_SND_SOC_MT2701_CS42448) += mt2701-cs42448.o
+obj-$(CONFIG_SND_SOC_MT2701_HDMI) += mt2701-hdmi.o
obj-$(CONFIG_SND_SOC_MT2701_WM8960) += mt2701-wm8960.o
diff --git a/sound/soc/mediatek/mt2701/mt2701-hdmi.c b/sound/soc/mediatek/mt2701/mt2701-hdmi.c
new file mode 100644
index 000000000000..a84907879c04
--- /dev/null
+++ b/sound/soc/mediatek/mt2701/mt2701-hdmi.c
@@ -0,0 +1,114 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * mt2701-hdmi.c -- MT2701 HDMI ALSA SoC machine driver
+ *
+ * Copyright (c) 2026 Daniel Golle <daniel@makrotopia.org>
+ *
+ * Based on mt2701-cs42448.c
+ */
+
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
+#include <sound/soc.h>
+
+enum {
+ DAI_LINK_FE_HDMI_OUT,
+ DAI_LINK_BE_HDMI_I2S,
+};
+
+SND_SOC_DAILINK_DEFS(fe_hdmi_out,
+ DAILINK_COMP_ARRAY(COMP_CPU("PCM_HDMI")),
+ DAILINK_COMP_ARRAY(COMP_DUMMY()),
+ DAILINK_COMP_ARRAY(COMP_EMPTY()));
+
+SND_SOC_DAILINK_DEFS(be_hdmi_i2s,
+ DAILINK_COMP_ARRAY(COMP_CPU("HDMI I2S")),
+ DAILINK_COMP_ARRAY(COMP_CODEC(NULL, "i2s-hifi")),
+ DAILINK_COMP_ARRAY(COMP_EMPTY()));
+
+static struct snd_soc_dai_link mt2701_hdmi_dai_links[] = {
+ [DAI_LINK_FE_HDMI_OUT] = {
+ .name = "HDMI Playback",
+ .stream_name = "HDMI Playback",
+ .trigger = { SND_SOC_DPCM_TRIGGER_POST,
+ SND_SOC_DPCM_TRIGGER_POST },
+ .dynamic = 1,
+ .playback_only = 1,
+ SND_SOC_DAILINK_REG(fe_hdmi_out),
+ },
+ [DAI_LINK_BE_HDMI_I2S] = {
+ .name = "HDMI BE",
+ .no_pcm = 1,
+ .playback_only = 1,
+ .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF |
+ SND_SOC_DAIFMT_CBC_CFC,
+ SND_SOC_DAILINK_REG(be_hdmi_i2s),
+ },
+};
+
+static struct snd_soc_card mt2701_hdmi_soc_card = {
+ .name = "mt2701-hdmi",
+ .owner = THIS_MODULE,
+ .dai_link = mt2701_hdmi_dai_links,
+ .num_links = ARRAY_SIZE(mt2701_hdmi_dai_links),
+};
+
+static int mt2701_hdmi_machine_probe(struct platform_device *pdev)
+{
+ struct snd_soc_card *card = &mt2701_hdmi_soc_card;
+ struct device *dev = &pdev->dev;
+ struct device_node *platform_node;
+ struct device_node *codec_node;
+ struct snd_soc_dai_link *dai_link;
+ int ret;
+ int i;
+
+ platform_node = of_parse_phandle(dev->of_node, "mediatek,platform", 0);
+ if (!platform_node)
+ return dev_err_probe(dev, -EINVAL,
+ "Property 'mediatek,platform' missing\n");
+
+ for_each_card_prelinks(card, i, dai_link) {
+ if (dai_link->platforms->name)
+ continue;
+ dai_link->platforms->of_node = platform_node;
+ }
+
+ codec_node = of_parse_phandle(dev->of_node, "mediatek,audio-codec", 0);
+ if (!codec_node) {
+ of_node_put(platform_node);
+ return dev_err_probe(dev, -EINVAL,
+ "Property 'mediatek,audio-codec' missing\n");
+ }
+ mt2701_hdmi_dai_links[DAI_LINK_BE_HDMI_I2S].codecs->of_node = codec_node;
+
+ card->dev = dev;
+
+ ret = devm_snd_soc_register_card(dev, card);
+
+ of_node_put(platform_node);
+ of_node_put(codec_node);
+ return ret;
+}
+
+static const struct of_device_id mt2701_hdmi_machine_dt_match[] = {
+ { .compatible = "mediatek,mt2701-hdmi-audio" },
+ { .compatible = "mediatek,mt7623n-hdmi-audio" },
+ {}
+};
+MODULE_DEVICE_TABLE(of, mt2701_hdmi_machine_dt_match);
+
+static struct platform_driver mt2701_hdmi_machine = {
+ .driver = {
+ .name = "mt2701-hdmi",
+ .of_match_table = mt2701_hdmi_machine_dt_match,
+ },
+ .probe = mt2701_hdmi_machine_probe,
+};
+module_platform_driver(mt2701_hdmi_machine);
+
+MODULE_DESCRIPTION("MT2701 HDMI ALSA SoC machine driver");
+MODULE_AUTHOR("Daniel Golle <daniel@makrotopia.org>");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:mt2701-hdmi");
--
2.54.0
^ permalink raw reply related
* [PATCH v3 5/9] ASoC: mediatek: mt2701: add HDMI audio memif, FE and BE DAIs
From: Daniel Golle @ 2026-04-24 2:50 UTC (permalink / raw)
To: Liam Girdwood, Mark Brown, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Matthias Brugger, AngeloGioacchino Del Regno,
Jaroslav Kysela, Takashi Iwai, Cyril Chao, Arnd Bergmann,
Nícolas F. R. A. Prado, Kuninori Morimoto, Daniel Golle,
Eugen Hristev, linux-sound, devicetree, linux-kernel,
linux-arm-kernel, linux-mediatek
In-Reply-To: <cover.1776998727.git.daniel@makrotopia.org>
Extend the MT2701/MT7623N AFE driver with the HDMI playback path:
- a new HDMI DMA memif (MT2701_MEMIF_HDMI) mapped to the
AFE_HDMI_OUT_{CON0,BASE,CUR,END} registers;
- a PCM_HDMI front-end DAI (S16_LE only, 44.1k/48k) which feeds
the memif via DPCM;
- an HDMI BE DAI wrapping the AFE_8CH_I2S_OUT_CON engine that
serialises L/R samples towards the on-chip HDMI transmitter.
Sample-rate programming uses the empirically determined
HDMI_BCK_DIV = 45 * 48000 / rate - 1 formula in AUDIO_TOP_CON3,
which covers 44.1 kHz and 48 kHz within the 6-bit divider range.
The AFE_HDMI_CONN0 interconnect is programmed to route memif
output pairs to the serializer inputs with L/R in the right order
for hdmi-audio-codec.
The existing I2S engine helpers (mt2701_mclk_configuration,
mt2701_i2s_path_enable, mt2701_afe_i2s_path_disable) are reused
for the HDMI BE so that MCLK at 128*fs and the ASYS I2S3 FS field
are programmed and cleanly released across open/close cycles.
Only S16_LE and 44.1k/48k are exposed to userspace. Other rates
fall outside the 6-bit BCK divider range, and wider sample
formats require DMA BIT_WIDTH programming that the current memif
setup does not handle. These limits match what the MT8173 AFE
driver exposes for its HDMI path.
The HDMI-related AFE registers (AUDIO_TOP_CON3, AFE_HDMI_OUT_CON0,
AFE_HDMI_CONN0, AFE_8CH_I2S_OUT_CON) are added to the suspend
backup list so that the existing mtk_afe_suspend/resume framework
saves and restores them across system sleep cycles.
Signed-off-by: Daniel Golle <daniel@makrotopia.org>
---
v3:
* remove redundant clock un-gating via regmap access
v2:
* use named masks and explicitly set BIT_WIDTH_16 when
programming AFE_HDMI_OUT_CON0 channel count (Mark Brown)
* add AUDIO_TOP_CON3, AFE_HDMI_OUT_CON0, AFE_HDMI_CONN0,
AFE_8CH_I2S_OUT_CON to suspend/resume backup list
(Mark Brown)
sound/soc/mediatek/mt2701/mt2701-afe-common.h | 2 +
sound/soc/mediatek/mt2701/mt2701-afe-pcm.c | 284 +++++++++++++++++-
2 files changed, 285 insertions(+), 1 deletion(-)
diff --git a/sound/soc/mediatek/mt2701/mt2701-afe-common.h b/sound/soc/mediatek/mt2701/mt2701-afe-common.h
index 7b15283d6351..8b6f3a200048 100644
--- a/sound/soc/mediatek/mt2701/mt2701-afe-common.h
+++ b/sound/soc/mediatek/mt2701/mt2701-afe-common.h
@@ -33,6 +33,7 @@ enum {
MT2701_MEMIF_UL5,
MT2701_MEMIF_DLBT,
MT2701_MEMIF_ULBT,
+ MT2701_MEMIF_HDMI,
MT2701_MEMIF_NUM,
MT2701_IO_I2S = MT2701_MEMIF_NUM,
MT2701_IO_2ND_I2S,
@@ -41,6 +42,7 @@ enum {
MT2701_IO_5TH_I2S,
MT2701_IO_6TH_I2S,
MT2701_IO_MRG,
+ MT2701_IO_HDMI,
};
enum {
diff --git a/sound/soc/mediatek/mt2701/mt2701-afe-pcm.c b/sound/soc/mediatek/mt2701/mt2701-afe-pcm.c
index fcae38135d93..bb459faa6e05 100644
--- a/sound/soc/mediatek/mt2701/mt2701-afe-pcm.c
+++ b/sound/soc/mediatek/mt2701/mt2701-afe-pcm.c
@@ -13,6 +13,7 @@
#include <linux/mfd/syscon.h>
#include <linux/of.h>
#include <linux/pm_runtime.h>
+#include <sound/pcm_params.h>
#include "mt2701-afe-common.h"
#include "mt2701-afe-clock-ctrl.h"
@@ -60,6 +61,7 @@ static const struct mt2701_afe_rate mt2701_afe_i2s_rates[] = {
static const unsigned int mt2701_afe_backup_list[] = {
AUDIO_TOP_CON0,
+ AUDIO_TOP_CON3,
AUDIO_TOP_CON4,
AUDIO_TOP_CON5,
ASYS_TOP_CON,
@@ -77,6 +79,9 @@ static const unsigned int mt2701_afe_backup_list[] = {
AFE_CONN22,
AFE_DAC_CON0,
AFE_MEMIF_PBUF_SIZE,
+ AFE_HDMI_OUT_CON0,
+ AFE_HDMI_CONN0,
+ AFE_8CH_I2S_OUT_CON,
};
static int mt2701_dai_num_to_i2s(struct mtk_base_afe *afe, int num)
@@ -542,6 +547,220 @@ static const struct snd_soc_dai_ops mt2701_btmrg_ops = {
.hw_params = mt2701_btmrg_hw_params,
};
+/*
+ * HDMI BE DAI -- drives the on-SoC 8-channel I2S engine whose output
+ * feeds the HDMI transmitter audio port.
+ *
+ * The HDMI audio hardware path is:
+ * HDMI memif DMA (AFE_HDMI_OUT_*) -> interconnect mux (AFE_HDMI_CONN0)
+ * -> 8-channel I2S engine (AFE_8CH_I2S_OUT_CON) -> HDMI TX audio port
+ *
+ * The I2S3 clock tree provides the bit/master clocks; we set its
+ * mclk_rate to 128*fs (matching HDMI_AUD_MCLK_128FS) and let
+ * mt2701_mclk_configuration program the PLL/divider path.
+ */
+#define MT2701_HDMI_I2S_PATH 3
+
+static int mt2701_afe_hdmi_startup(struct snd_pcm_substream *substream,
+ struct snd_soc_dai *dai)
+{
+ struct mtk_base_afe *afe = snd_soc_dai_get_drvdata(dai);
+ struct mt2701_afe_private *afe_priv = afe->platform_priv;
+ int ret;
+
+ if (!afe_priv->hadds2pll_ck || !afe_priv->audio_hdmi_ck) {
+ dev_err(afe->dev, "HDMI audio clocks not available\n");
+ return -ENODEV;
+ }
+
+ ret = clk_prepare_enable(afe_priv->hadds2pll_ck);
+ if (ret)
+ return ret;
+
+ ret = clk_prepare_enable(afe_priv->audio_hdmi_ck);
+ if (ret)
+ goto err_hdmi;
+
+ if (afe_priv->audio_spdf_ck) {
+ ret = clk_prepare_enable(afe_priv->audio_spdf_ck);
+ if (ret)
+ goto err_spdf;
+ }
+
+ if (afe_priv->audio_apll_ck) {
+ ret = clk_prepare_enable(afe_priv->audio_apll_ck);
+ if (ret)
+ goto err_apll;
+ }
+
+ ret = mt2701_afe_enable_mclk(afe, MT2701_HDMI_I2S_PATH);
+ if (ret)
+ goto err_mclk;
+
+ return 0;
+
+err_mclk:
+ if (afe_priv->audio_apll_ck)
+ clk_disable_unprepare(afe_priv->audio_apll_ck);
+err_apll:
+ if (afe_priv->audio_spdf_ck)
+ clk_disable_unprepare(afe_priv->audio_spdf_ck);
+err_spdf:
+ clk_disable_unprepare(afe_priv->audio_hdmi_ck);
+err_hdmi:
+ clk_disable_unprepare(afe_priv->hadds2pll_ck);
+ return ret;
+}
+
+static void mt2701_afe_hdmi_shutdown(struct snd_pcm_substream *substream,
+ struct snd_soc_dai *dai)
+{
+ struct mtk_base_afe *afe = snd_soc_dai_get_drvdata(dai);
+ struct mt2701_afe_private *afe_priv = afe->platform_priv;
+
+ mt2701_afe_disable_mclk(afe, MT2701_HDMI_I2S_PATH);
+ if (afe_priv->audio_apll_ck)
+ clk_disable_unprepare(afe_priv->audio_apll_ck);
+ if (afe_priv->audio_spdf_ck)
+ clk_disable_unprepare(afe_priv->audio_spdf_ck);
+ clk_disable_unprepare(afe_priv->audio_hdmi_ck);
+ clk_disable_unprepare(afe_priv->hadds2pll_ck);
+}
+
+static int mt2701_afe_hdmi_hw_params(struct snd_pcm_substream *substream,
+ struct snd_pcm_hw_params *params,
+ struct snd_soc_dai *dai)
+{
+ struct mtk_base_afe *afe = snd_soc_dai_get_drvdata(dai);
+ struct mt2701_afe_private *afe_priv = afe->platform_priv;
+ unsigned int channels = params_channels(params);
+ unsigned int rate = params_rate(params);
+ unsigned int divp1;
+ unsigned int val;
+ unsigned int i;
+ int ret;
+
+ /*
+ * Compute AUDIO_TOP_CON3.HDMI_BCK_DIV up front. The divider
+ * drives an internal reference for the HDMI transmitter's
+ * audio packet engine; it must scale with the sample rate so
+ * that the packet engine's timing matches the data flowing in
+ * from the AFE memif/I2S3 side. Empirically, with audpll_sel
+ * parented to hadds2pll_98m (98.304 MHz), the correct value at
+ * 48 kHz is div = 44 (i.e. (div+1) = 45), giving 1.0923 MHz.
+ * Scaling inversely with rate: (div + 1) = 45 * 48000 / rate.
+ * Integer rounding introduces small (<1%) errors at 32 kHz;
+ * 44.1 kHz is nearly exact via round-to-nearest. Reject rates
+ * that fall outside the 6-bit divider range before touching
+ * any hardware so no side effects are left behind on error.
+ */
+ divp1 = (45U * 48000U + rate / 2) / rate;
+ if (divp1 == 0 || divp1 > 64)
+ return -EINVAL;
+
+ /*
+ * Park the I2S3 clock tree at 128*fs -- this is the MCLK that
+ * the ASYS I2S3 engine uses to derive its BCK/LRCK. The engine
+ * outputs BCK = 64*fs (stereo, 32-bit word length).
+ */
+ afe_priv->i2s_path[MT2701_HDMI_I2S_PATH].mclk_rate = rate * 128;
+ ret = mt2701_mclk_configuration(afe, MT2701_HDMI_I2S_PATH);
+ if (ret)
+ return ret;
+
+ /* Program and start the ASYS I2S3 engine (FS, I2S mode, enable). */
+ mt2701_i2s_path_enable(afe,
+ &afe_priv->i2s_path[MT2701_HDMI_I2S_PATH],
+ SNDRV_PCM_STREAM_PLAYBACK, rate);
+
+ regmap_update_bits(afe->regmap, AUDIO_TOP_CON3,
+ AUDIO_TOP_CON3_HDMI_BCK_DIV_MASK,
+ AUDIO_TOP_CON3_HDMI_BCK_DIV(divp1 - 1));
+
+ /*
+ * HDMI output memif: set channel count and confirm 16-bit
+ * sample width. Both fields must be written together so that
+ * stale reset-default or prior-stream values in BIT_WIDTH
+ * cannot persist.
+ */
+ regmap_update_bits(afe->regmap, AFE_HDMI_OUT_CON0,
+ AFE_HDMI_OUT_CON0_CH_NUM_MASK |
+ AFE_HDMI_OUT_CON0_BIT_WIDTH_MASK,
+ AFE_HDMI_OUT_CON0_CH_NUM(channels) |
+ AFE_HDMI_OUT_CON0_BIT_WIDTH_16);
+
+ /*
+ * Interconnect mux -- map DMA input slots to HDMI output slots.
+ * Each output takes a 3-bit field at shift (i*3). Swap the first
+ * two inputs so that the DMA's interleaved L/R pair lands on the
+ * correct HDMI L/R output slots. Remaining slots are identity.
+ */
+ val = (1 << 0) | (0 << 3); /* O20 <- I21, O21 <- I20 */
+ for (i = 2; i < 8; i++)
+ val |= ((i & 0x7) << (i * 3));
+ regmap_write(afe->regmap, AFE_HDMI_CONN0, val);
+
+ /*
+ * 8-channel I2S framing: standard I2S, 32-bit slots,
+ * LRCK/BCK inverted. The wire protocol is fixed.
+ */
+ regmap_update_bits(afe->regmap, AFE_8CH_I2S_OUT_CON,
+ AFE_8CH_I2S_OUT_CON_WLEN_MASK |
+ AFE_8CH_I2S_OUT_CON_I2S_DELAY |
+ AFE_8CH_I2S_OUT_CON_LRCK_INV |
+ AFE_8CH_I2S_OUT_CON_BCK_INV,
+ AFE_8CH_I2S_OUT_CON_WLEN_32BIT |
+ AFE_8CH_I2S_OUT_CON_I2S_DELAY |
+ AFE_8CH_I2S_OUT_CON_LRCK_INV |
+ AFE_8CH_I2S_OUT_CON_BCK_INV);
+ return 0;
+}
+
+static int mt2701_afe_hdmi_trigger(struct snd_pcm_substream *substream, int cmd,
+ struct snd_soc_dai *dai)
+{
+ struct mtk_base_afe *afe = snd_soc_dai_get_drvdata(dai);
+
+ switch (cmd) {
+ case SNDRV_PCM_TRIGGER_START:
+ case SNDRV_PCM_TRIGGER_RESUME:
+ /* Enable HDMI output memif. */
+ regmap_update_bits(afe->regmap, AFE_HDMI_OUT_CON0, 0x1, 0x1);
+ /* Enable 8-channel I2S engine. */
+ regmap_update_bits(afe->regmap, AFE_8CH_I2S_OUT_CON,
+ AFE_8CH_I2S_OUT_CON_EN,
+ AFE_8CH_I2S_OUT_CON_EN);
+ return 0;
+ case SNDRV_PCM_TRIGGER_STOP:
+ case SNDRV_PCM_TRIGGER_SUSPEND:
+ regmap_update_bits(afe->regmap, AFE_8CH_I2S_OUT_CON,
+ AFE_8CH_I2S_OUT_CON_EN, 0);
+ regmap_update_bits(afe->regmap, AFE_HDMI_OUT_CON0, 0x1, 0);
+ return 0;
+ }
+ return -EINVAL;
+}
+
+static int mt2701_afe_hdmi_hw_free(struct snd_pcm_substream *substream,
+ struct snd_soc_dai *dai)
+{
+ struct mtk_base_afe *afe = snd_soc_dai_get_drvdata(dai);
+ struct mt2701_afe_private *afe_priv = afe->platform_priv;
+
+ mt2701_afe_i2s_path_disable(afe,
+ &afe_priv->i2s_path[MT2701_HDMI_I2S_PATH],
+ SNDRV_PCM_STREAM_PLAYBACK);
+ return 0;
+}
+
+static const struct snd_soc_dai_ops mt2701_afe_hdmi_ops = {
+ .startup = mt2701_afe_hdmi_startup,
+ .shutdown = mt2701_afe_hdmi_shutdown,
+ .hw_params = mt2701_afe_hdmi_hw_params,
+ .hw_free = mt2701_afe_hdmi_hw_free,
+ .trigger = mt2701_afe_hdmi_trigger,
+};
+
static struct snd_soc_dai_driver mt2701_afe_pcm_dais[] = {
/* FE DAIs: memory intefaces to CPU */
{
@@ -628,6 +847,19 @@ static struct snd_soc_dai_driver mt2701_afe_pcm_dais[] = {
},
.ops = &mt2701_single_memif_dai_ops,
},
+ {
+ .name = "PCM_HDMI",
+ .id = MT2701_MEMIF_HDMI,
+ .playback = {
+ .stream_name = "HDMI Multich",
+ .channels_min = 2,
+ .channels_max = 8,
+ .rates = (SNDRV_PCM_RATE_44100 |
+ SNDRV_PCM_RATE_48000),
+ .formats = SNDRV_PCM_FMTBIT_S16_LE,
+ },
+ .ops = &mt2701_single_memif_dai_ops,
+ },
/* BE DAIs */
{
.name = "I2S0",
@@ -748,7 +980,20 @@ static struct snd_soc_dai_driver mt2701_afe_pcm_dais[] = {
},
.ops = &mt2701_btmrg_ops,
.symmetric_rate = 1,
- }
+ },
+ {
+ .name = "HDMI I2S",
+ .id = MT2701_IO_HDMI,
+ .playback = {
+ .stream_name = "HDMI 8CH I2S Playback",
+ .channels_min = 2,
+ .channels_max = 8,
+ .rates = (SNDRV_PCM_RATE_44100 |
+ SNDRV_PCM_RATE_48000),
+ .formats = SNDRV_PCM_FMTBIT_S16_LE,
+ },
+ .ops = &mt2701_afe_hdmi_ops,
+ },
};
static const struct snd_kcontrol_new mt2701_afe_o00_mix[] = {
@@ -927,6 +1172,14 @@ static const struct snd_soc_dapm_route mt2701_afe_pcm_routes[] = {
{"I16I17", "Multich I2S2 Out Switch", "DLM"},
{"I18I19", "Multich I2S3 Out Switch", "DLM"},
+ /*
+ * HDMI FE -> BE direct route. The HDMI memif has its own DMA
+ * path that feeds the 8-channel internal I2S straight into the
+ * HDMI transmitter; no mixer/interconnect selection is exposed
+ * to the user.
+ */
+ {"HDMI 8CH I2S Playback", NULL, "HDMI Multich"},
+
{ "I12", NULL, "I12I13" },
{ "I13", NULL, "I12I13" },
{ "I14", NULL, "I14I15" },
@@ -1207,6 +1460,35 @@ static const struct mtk_base_memif_data memif_data_array[MT2701_MEMIF_NUM] = {
.agent_disable_shift = 16,
.msb_reg = -1,
},
+ {
+ /*
+ * HDMI memif feeds the on-SoC 8-channel internal I2S that
+ * drives the HDMI transmitter audio port. Unlike the
+ * standard memifs, the enable bit, channel count and bit
+ * width all live in AFE_HDMI_OUT_CON0, so mono/fs/hd/agent
+ * fields are left at -1 and programmed from the BE DAI ops
+ * instead.
+ */
+ .name = "HDMI",
+ .id = MT2701_MEMIF_HDMI,
+ .reg_ofs_base = AFE_HDMI_OUT_BASE,
+ .reg_ofs_cur = AFE_HDMI_OUT_CUR,
+ .reg_ofs_end = AFE_HDMI_OUT_END,
+ .fs_reg = -1,
+ .fs_shift = -1,
+ .fs_maskbit = 0,
+ .mono_reg = -1,
+ .mono_shift = -1,
+ .enable_reg = AFE_HDMI_OUT_CON0,
+ .enable_shift = 0,
+ .hd_reg = -1,
+ .hd_shift = -1,
+ .hd_align_reg = -1,
+ .hd_align_mshift = 0,
+ .agent_disable_reg = -1,
+ .agent_disable_shift = 0,
+ .msb_reg = -1,
+ },
};
static const struct mtk_base_irq_data irq_data[MT2701_IRQ_ASYS_END] = {
--
2.54.0
^ permalink raw reply related
* [PATCH v3 4/9] ASoC: mediatek: mt2701: add optional HDMI audio path clocks
From: Daniel Golle @ 2026-04-24 2:49 UTC (permalink / raw)
To: Liam Girdwood, Mark Brown, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Matthias Brugger, AngeloGioacchino Del Regno,
Jaroslav Kysela, Takashi Iwai, Cyril Chao, Arnd Bergmann,
Nícolas F. R. A. Prado, Kuninori Morimoto, Daniel Golle,
Eugen Hristev, linux-sound, devicetree, linux-kernel,
linux-arm-kernel, linux-mediatek
In-Reply-To: <cover.1776998727.git.daniel@makrotopia.org>
The HDMI audio output path on MT2701/MT7623N is rooted in HADDS2PLL
and gated by the audio_hdmi, audio_spdf and audio_apll power gates.
Acquire these four clocks from device tree using devm_clk_get_optional
so that existing platforms which do not wire up HDMI audio keep
probing unchanged. Actual clock enable/prepare is deferred to the
upcoming HDMI DAI startup path.
Signed-off-by: Daniel Golle <daniel@makrotopia.org>
---
v3: no changes
v2: no changes
.../mediatek/mt2701/mt2701-afe-clock-ctrl.c | 22 +++++++++++++++++++
sound/soc/mediatek/mt2701/mt2701-afe-common.h | 4 ++++
2 files changed, 26 insertions(+)
diff --git a/sound/soc/mediatek/mt2701/mt2701-afe-clock-ctrl.c b/sound/soc/mediatek/mt2701/mt2701-afe-clock-ctrl.c
index ae620890bb3a..5a2bcf027b4f 100644
--- a/sound/soc/mediatek/mt2701/mt2701-afe-clock-ctrl.c
+++ b/sound/soc/mediatek/mt2701/mt2701-afe-clock-ctrl.c
@@ -95,6 +95,28 @@ int mt2701_init_clock(struct mtk_base_afe *afe)
afe_priv->mrgif_ck = NULL;
}
+ /*
+ * Optional HDMI audio clocks. Platforms that do not wire up the
+ * HDMI output (e.g. MT2701 devkits using only the I2S BE DAIs)
+ * may omit these; in that case the HDMI BE DAI simply cannot be
+ * enabled, but the rest of the AFE still probes.
+ */
+ afe_priv->hadds2pll_ck = devm_clk_get_optional(afe->dev, "hadds2pll_294m");
+ if (IS_ERR(afe_priv->hadds2pll_ck))
+ return PTR_ERR(afe_priv->hadds2pll_ck);
+
+ afe_priv->audio_hdmi_ck = devm_clk_get_optional(afe->dev, "audio_hdmi_pd");
+ if (IS_ERR(afe_priv->audio_hdmi_ck))
+ return PTR_ERR(afe_priv->audio_hdmi_ck);
+
+ afe_priv->audio_spdf_ck = devm_clk_get_optional(afe->dev, "audio_spdf_pd");
+ if (IS_ERR(afe_priv->audio_spdf_ck))
+ return PTR_ERR(afe_priv->audio_spdf_ck);
+
+ afe_priv->audio_apll_ck = devm_clk_get_optional(afe->dev, "audio_apll_pd");
+ if (IS_ERR(afe_priv->audio_apll_ck))
+ return PTR_ERR(afe_priv->audio_apll_ck);
+
return 0;
}
diff --git a/sound/soc/mediatek/mt2701/mt2701-afe-common.h b/sound/soc/mediatek/mt2701/mt2701-afe-common.h
index 32bef5e2a56d..7b15283d6351 100644
--- a/sound/soc/mediatek/mt2701/mt2701-afe-common.h
+++ b/sound/soc/mediatek/mt2701/mt2701-afe-common.h
@@ -90,6 +90,10 @@ struct mt2701_afe_private {
struct mt2701_i2s_path *i2s_path;
struct clk *base_ck[MT2701_BASE_CLK_NUM];
struct clk *mrgif_ck;
+ struct clk *hadds2pll_ck;
+ struct clk *audio_hdmi_ck;
+ struct clk *audio_spdf_ck;
+ struct clk *audio_apll_ck;
bool mrg_enable[MTK_STREAM_NUM];
const struct mt2701_soc_variants *soc;
--
2.54.0
^ permalink raw reply related
* [PATCH v3 3/9] ASoC: mediatek: mt2701: add AFE HDMI register definitions
From: Daniel Golle @ 2026-04-24 2:49 UTC (permalink / raw)
To: Liam Girdwood, Mark Brown, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Matthias Brugger, AngeloGioacchino Del Regno,
Jaroslav Kysela, Takashi Iwai, Cyril Chao, Arnd Bergmann,
Nícolas F. R. A. Prado, Kuninori Morimoto, Daniel Golle,
Eugen Hristev, linux-sound, devicetree, linux-kernel,
linux-arm-kernel, linux-mediatek
In-Reply-To: <cover.1776998727.git.daniel@makrotopia.org>
Add register offsets and bit defines for the MT2701/MT7623N AFE
HDMI audio output path: the HDMI BCK divider in AUDIO_TOP_CON3,
the HDMI output memif control and descriptor registers, the 8-bit
AFE_HDMI_CONN0 interconnect, and the AFE_8CH_I2S_OUT_CON engine
that drives the HDMI TX serial link. These are a prerequisite for
adding an HDMI playback path to the mt2701 AFE driver and have no
behavioural effect on their own.
Signed-off-by: Daniel Golle <daniel@makrotopia.org>
---
v3: remove now unused clk bits
v2: no changes
sound/soc/mediatek/mt2701/mt2701-reg.h | 29 ++++++++++++++++++++++++++
1 file changed, 29 insertions(+)
diff --git a/sound/soc/mediatek/mt2701/mt2701-reg.h b/sound/soc/mediatek/mt2701/mt2701-reg.h
index c84d14cdd7ae..ca914df02c96 100644
--- a/sound/soc/mediatek/mt2701/mt2701-reg.h
+++ b/sound/soc/mediatek/mt2701/mt2701-reg.h
@@ -10,10 +10,17 @@
#define _MT2701_REG_H_
#define AUDIO_TOP_CON0 0x0000
+#define AUDIO_TOP_CON3 0x000c
#define AUDIO_TOP_CON4 0x0010
#define AUDIO_TOP_CON5 0x0014
#define AFE_DAIBT_CON0 0x001c
#define AFE_MRGIF_CON 0x003c
+#define AFE_HDMI_OUT_CON0 0x0370
+#define AFE_HDMI_OUT_BASE 0x0374
+#define AFE_HDMI_OUT_CUR 0x0378
+#define AFE_HDMI_OUT_END 0x037c
+#define AFE_HDMI_CONN0 0x0390
+#define AFE_8CH_I2S_OUT_CON 0x0394
#define ASMI_TIMING_CON1 0x0100
#define ASMO_TIMING_CON1 0x0104
#define PWR1_ASM_CON1 0x0108
@@ -125,6 +132,28 @@
#define AFE_MEMIF_PBUF_SIZE_DLM_BYTE_MASK (0x3 << 12)
#define AFE_MEMIF_PBUF_SIZE_DLM_32BYTES (0x1 << 12)
+/* AUDIO_TOP_CON3 (0x000c) -- HDMI BCK divider */
+#define AUDIO_TOP_CON3_HDMI_BCK_DIV_MASK (0x3f << 8)
+#define AUDIO_TOP_CON3_HDMI_BCK_DIV(x) (((x) & 0x3f) << 8)
+
+/* AFE_HDMI_OUT_CON0 (0x0370) */
+#define AFE_HDMI_OUT_CON0_OUT_ON (0x1 << 0)
+#define AFE_HDMI_OUT_CON0_BIT_WIDTH_MASK (0x1 << 1)
+#define AFE_HDMI_OUT_CON0_BIT_WIDTH_16 (0x0 << 1)
+#define AFE_HDMI_OUT_CON0_BIT_WIDTH_32 (0x1 << 1)
+#define AFE_HDMI_OUT_CON0_CH_NUM_MASK (0xf << 4)
+#define AFE_HDMI_OUT_CON0_CH_NUM(x) (((x) & 0xf) << 4)
+
+/* AFE_8CH_I2S_OUT_CON (0x0394) -- on-SoC 8-channel I2S that feeds HDMI TX */
+#define AFE_8CH_I2S_OUT_CON_EN (0x1 << 0)
+#define AFE_8CH_I2S_OUT_CON_BCK_INV (0x1 << 1)
+#define AFE_8CH_I2S_OUT_CON_LRCK_INV (0x1 << 2)
+#define AFE_8CH_I2S_OUT_CON_I2S_DELAY (0x1 << 3)
+#define AFE_8CH_I2S_OUT_CON_WLEN_MASK (0x3 << 4)
+#define AFE_8CH_I2S_OUT_CON_WLEN_16BIT (0x1 << 4)
+#define AFE_8CH_I2S_OUT_CON_WLEN_24BIT (0x2 << 4)
+#define AFE_8CH_I2S_OUT_CON_WLEN_32BIT (0x3 << 4)
+
/* I2S in/out register bit control */
#define ASYS_I2S_CON_FS (0x1f << 8)
#define ASYS_I2S_CON_FS_SET(x) ((x) << 8)
--
2.54.0
^ permalink raw reply related
* [PATCH v3 2/9] ASoC: dt-bindings: mediatek,mt2701-hdmi-audio: add MT2701 HDMI audio
From: Daniel Golle @ 2026-04-24 2:48 UTC (permalink / raw)
To: Liam Girdwood, Mark Brown, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Matthias Brugger, AngeloGioacchino Del Regno,
Jaroslav Kysela, Takashi Iwai, Cyril Chao, Arnd Bergmann,
Nícolas F. R. A. Prado, Kuninori Morimoto, Daniel Golle,
Eugen Hristev, linux-sound, devicetree, linux-kernel,
linux-arm-kernel, linux-mediatek
In-Reply-To: <cover.1776998727.git.daniel@makrotopia.org>
Describe the sound card node that routes the MT2701/MT7623N AFE
HDMI playback path to the on-chip HDMI transmitter. This is
separate from the AFE platform binding (mediatek,mt2701-audio)
because it represents board-level audio routing between the AFE
and the HDMI codec, not an additional IP block. MT7623N boards
carry the same IP and use the mt7623n- compatible as a fallback
to mt2701-.
Signed-off-by: Daniel Golle <daniel@makrotopia.org>
Reviewed-by: Krzysztof Kozlowski <krzysztof.kozlowski@oss.qualcomm.com>
---
v3: no changes
v2:
* Fix subject prefix to use schema filename (Krzysztof Kozlowski)
* Rewrite title and description to describe hardware, not driver
(Krzysztof Kozlowski)
* Clarify in commit message why this is a separate binding from
mediatek,mt2701-audio (Krzysztof Kozlowski)
.../sound/mediatek,mt2701-hdmi-audio.yaml | 48 +++++++++++++++++++
1 file changed, 48 insertions(+)
create mode 100644 Documentation/devicetree/bindings/sound/mediatek,mt2701-hdmi-audio.yaml
diff --git a/Documentation/devicetree/bindings/sound/mediatek,mt2701-hdmi-audio.yaml b/Documentation/devicetree/bindings/sound/mediatek,mt2701-hdmi-audio.yaml
new file mode 100644
index 000000000000..9d5a8166e51f
--- /dev/null
+++ b/Documentation/devicetree/bindings/sound/mediatek,mt2701-hdmi-audio.yaml
@@ -0,0 +1,48 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/sound/mediatek,mt2701-hdmi-audio.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: MediaTek MT2701/MT7623N HDMI audio output
+
+maintainers:
+ - Daniel Golle <daniel@makrotopia.org>
+
+description:
+ Sound card routing the MT2701/MT7623N Audio Front End HDMI
+ playback path to the on-chip HDMI transmitter. The AFE
+ provides the DMA memif and internal I2S engine; the HDMI
+ transmitter acts as the audio codec on the serialised link.
+
+properties:
+ compatible:
+ oneOf:
+ - const: mediatek,mt2701-hdmi-audio
+ - items:
+ - const: mediatek,mt7623n-hdmi-audio
+ - const: mediatek,mt2701-hdmi-audio
+
+ mediatek,platform:
+ $ref: /schemas/types.yaml#/definitions/phandle
+ description: Phandle of the MT2701/MT7623N AFE platform node.
+
+ mediatek,audio-codec:
+ $ref: /schemas/types.yaml#/definitions/phandle
+ description: Phandle of the HDMI transmitter acting as audio codec.
+
+required:
+ - compatible
+ - mediatek,platform
+ - mediatek,audio-codec
+
+additionalProperties: false
+
+examples:
+ - |
+ sound-hdmi {
+ compatible = "mediatek,mt7623n-hdmi-audio",
+ "mediatek,mt2701-hdmi-audio";
+ mediatek,platform = <&afe>;
+ mediatek,audio-codec = <&hdmi0>;
+ };
--
2.54.0
^ permalink raw reply related
* [PATCH v3 1/9] ASoC: dt-bindings: mt2701-afe-pcm: add HDMI audio path clocks
From: Daniel Golle @ 2026-04-24 2:48 UTC (permalink / raw)
To: Liam Girdwood, Mark Brown, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Matthias Brugger, AngeloGioacchino Del Regno,
Jaroslav Kysela, Takashi Iwai, Cyril Chao, Arnd Bergmann,
Nícolas F. R. A. Prado, Kuninori Morimoto, Daniel Golle,
Eugen Hristev, linux-sound, devicetree, linux-kernel,
linux-arm-kernel, linux-mediatek
In-Reply-To: <cover.1776998727.git.daniel@makrotopia.org>
Document four additional optional clocks feeding the HDMI audio
output path on MT2701: the HADDS2 PLL (root of the HDMI audio
clock tree), the HDMI audio and S/PDIF interface power gates,
and the audio APLL root gate. Older device trees that do not
wire these up remain valid via minItems. MT7622 does not have
HDMI audio hardware, so its compatible is restricted to the
base set of 34 clocks.
Signed-off-by: Daniel Golle <daniel@makrotopia.org>
Reviewed-by: Krzysztof Kozlowski <krzysztof.kozlowski@oss.qualcomm.com>
---
v3: allOf goes before additionalProperties
v2:
* Restrict the four HDMI clocks to mediatek,mt2701-audio only
using an allOf/if/then conditional; MT7622 is capped at 34
clocks (Krzysztof Kozlowski)
.../bindings/sound/mediatek,mt2701-audio.yaml | 23 +++++++++++++++++++
1 file changed, 23 insertions(+)
diff --git a/Documentation/devicetree/bindings/sound/mediatek,mt2701-audio.yaml b/Documentation/devicetree/bindings/sound/mediatek,mt2701-audio.yaml
index 45382c4d86aa..30f331366566 100644
--- a/Documentation/devicetree/bindings/sound/mediatek,mt2701-audio.yaml
+++ b/Documentation/devicetree/bindings/sound/mediatek,mt2701-audio.yaml
@@ -32,6 +32,7 @@ properties:
maxItems: 1
clocks:
+ minItems: 34
items:
- description: audio infra sys clock
- description: top audio mux 1
@@ -67,8 +68,13 @@ properties:
- description: top audio a1 sys pd
- description: top audio a2 sys pd
- description: audio merge interface pd
+ - description: HADDS2 PLL 294 MHz (HDMI audio path root)
+ - description: HDMI audio interface pd
+ - description: S/PDIF interface pd
+ - description: audio APLL root pd
clock-names:
+ minItems: 34
items:
- const: infra_sys_audio_clk
- const: top_audio_mux1_sel
@@ -104,6 +110,10 @@ properties:
- const: audio_a1sys_pd
- const: audio_a2sys_pd
- const: audio_mrgif_pd
+ - const: hadds2pll_294m
+ - const: audio_hdmi_pd
+ - const: audio_spdf_pd
+ - const: audio_apll_pd
required:
- compatible
@@ -113,4 +123,17 @@ required:
- clocks
- clock-names
+allOf:
+ - if:
+ properties:
+ compatible:
+ contains:
+ const: mediatek,mt7622-audio
+ then:
+ properties:
+ clocks:
+ maxItems: 34
+ clock-names:
+ maxItems: 34
+
additionalProperties: false
--
2.54.0
^ permalink raw reply related
* [PATCH v3 0/9] ASoC: mediatek: mt2701: HDMI audio support
From: Daniel Golle @ 2026-04-24 2:48 UTC (permalink / raw)
To: Liam Girdwood, Mark Brown, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Matthias Brugger, AngeloGioacchino Del Regno,
Jaroslav Kysela, Takashi Iwai, Cyril Chao, Arnd Bergmann,
Nícolas F. R. A. Prado, Kuninori Morimoto, Daniel Golle,
Eugen Hristev, linux-sound, devicetree, linux-kernel,
linux-arm-kernel, linux-mediatek
This series wires up on-chip HDMI audio on MT2701 and MT7623N, from the
DRM bridge down through the AFE into a small machine driver that binds
the AFE HDMI BE to the HDMI TX codec already exposed by the
mediatek-drm-hdmi driver. Bindings, DT and a BananaPi R2 board node
are included.
In order to survive vblank or late hotplug of the monitor, the fix
submitted separately [1] is required as well.
Everything here was developed for and tested on a BananaPi R2
(MT7623N), which turns ten years old this year -- a nice occasion to
finally land HDMI audio for a SoC which was truly ahead of its time.
[1]: https://patchwork.kernel.org/project/linux-mediatek/patch/a3e22cbae528c9a38d854a586d1736b860998d41.1776265222.git.daniel@makrotopia.org/
Changes since v2:
* allOf goes before additionalProperties
* remove now unused clk bits
* remove redundant clock un-gating via regmap access
Changes since v1:
* Restrict the four HDMI clocks to mediatek,mt2701-audio only
using an allOf/if/then conditional; MT7622 is capped at 34
clocks (Krzysztof Kozlowski)
* Fix subject prefix to use schema filename (Krzysztof Kozlowski)
* Rewrite title and description to describe hardware, not driver
(Krzysztof Kozlowski)
* Clarify in commit message why this is a separate binding from
mediatek,mt2701-audio (Krzysztof Kozlowski)
* use named masks and explicitly set BIT_WIDTH_16 when
programming AFE_HDMI_OUT_CON0 channel count (Mark Brown)
* add AUDIO_TOP_CON3, AFE_HDMI_OUT_CON0, AFE_HDMI_CONN0,
AFE_8CH_I2S_OUT_CON to suspend/resume backup list
(Mark Brown)
Daniel Golle (9):
ASoC: dt-bindings: mt2701-afe-pcm: add HDMI audio path clocks
ASoC: dt-bindings: mediatek,mt2701-hdmi-audio: add MT2701 HDMI audio
ASoC: mediatek: mt2701: add AFE HDMI register definitions
ASoC: mediatek: mt2701: add optional HDMI audio path clocks
ASoC: mediatek: mt2701: add HDMI audio memif, FE and BE DAIs
ASoC: mediatek: mt2701: add machine driver for on-chip HDMI codec
ARM: dts: mediatek: mt2701: wire HDMI audio path clocks into AFE
ARM: dts: mediatek: mt7623: wire HDMI audio path clocks into AFE
ARM: dts: mediatek: mt7623n-bananapi-bpi-r2: add HDMI audio machine
node
.../bindings/sound/mediatek,mt2701-audio.yaml | 23 ++
.../sound/mediatek,mt2701-hdmi-audio.yaml | 48 +++
arch/arm/boot/dts/mediatek/mt2701.dtsi | 21 +-
arch/arm/boot/dts/mediatek/mt7623.dtsi | 21 +-
.../dts/mediatek/mt7623n-bananapi-bpi-r2.dts | 7 +
sound/soc/mediatek/Kconfig | 10 +
sound/soc/mediatek/mt2701/Makefile | 1 +
.../mediatek/mt2701/mt2701-afe-clock-ctrl.c | 22 ++
sound/soc/mediatek/mt2701/mt2701-afe-common.h | 6 +
sound/soc/mediatek/mt2701/mt2701-afe-pcm.c | 284 +++++++++++++++++-
sound/soc/mediatek/mt2701/mt2701-hdmi.c | 114 +++++++
sound/soc/mediatek/mt2701/mt2701-reg.h | 29 ++
12 files changed, 575 insertions(+), 11 deletions(-)
create mode 100644 Documentation/devicetree/bindings/sound/mediatek,mt2701-hdmi-audio.yaml
create mode 100644 sound/soc/mediatek/mt2701/mt2701-hdmi.c
--
2.54.0
^ permalink raw reply
* Re: [PATCH] cpu/hotplug: Fix NULL kobject warning in cpuhp_smt_enable()
From: Jinjie Ruan @ 2026-04-24 2:47 UTC (permalink / raw)
To: Catalin Marinas
Cc: Thomas Gleixner, peterz, sudeep.holla, yangyicong,
dietmar.eggemann, Jonathan.Cameron, linux-kernel, James Morse,
linux-arm-kernel
In-Reply-To: <aep85G05D3TM9uj2@arm.com>
On 4/24/2026 4:11 AM, Catalin Marinas wrote:
> On Thu, Apr 23, 2026 at 08:32:34PM +0800, Jinjie Ruan wrote:
>> On 4/23/2026 6:08 PM, Thomas Gleixner wrote:
>>> On Sat, Apr 18 2026 at 12:55, Catalin Marinas wrote:
>>>> Another option would have been to avoid marking such CPUs present but I
>>>> think this will break other things. Yet another option is to register
>>>> all CPU devices even if they never come up (like maxcpus greater than
>>>> actual CPUs).
>>>>
>>>> Opinions? It might be an arm64+ACPI-only thing.
>>>
>>> I think so. The proper thing to do is to apply sane limits:
>>>
>>> 1) The possible CPUs enumerated by firmware N_POSSIBLE_FW
>>>
>>> 2) The maxcpus limit on the command line N_MAXCPUS_CL
>>>
>>> So the actual possible CPUs evaluates to:
>>>
>>> num_possible = min(N_POSSIBLE_FW, N_MAXCPUS_CL, CONFIG_NR_CPUS);
>>>
>>> The evaluation of the firmware should not mark CPUs present which are
>>> actually not. ACPI gives you that information. See:
>>>
>>> 5.2.12.14 GIC CPU Interface (GICC) Structure
>>>
>>> in the ACPI spec. That has two related bits:
>>>
>>> Enabled:
>>>
>>> If this bit is set, the processor is ready for use. If this bit is
>>> clear and the Online Capable bit is set, the system supports enabling
>>> this processor during OS runtime. If this bit is clear and the Online
>>> Capable bit is also clear, this processor is un- usable, and the
>>> operating system support will not attempt to use it.
>>>
>>> Online Capable:
>>>
>>> The information conveyed by this bit depends on the value of the
>>> Enabled bit. If the Enabled bit is set, this bit is reserved and must
>>> be zero. Otherwise, if this bit is set, the system supports enabling
>>> this processor later during OS runtime
>>>
>>> So the combination of those gives you the right answer:
>>>
>>> Enabled Online
>>> Capable
>>> 0 0 Not present, not possible
>>> 0 1 Not present, but possible to "hotplug" layter
>>> 1 0 Present
>>> 1 1 Invalid
>>
>> On x86, it seems that all CPUs with the ACPI_MADT_ENABLED bit set will
>> be marked as present.
>>
>> acpi_parse_x2apic()
>> -> enabled = processor->lapic_flags & ACPI_MADT_ENABLED
>> -> topology_register_apic(enabled)
>> -> topo_register_apic(enabled)
>> -> set_cpu_present(cpu, true)
>
> Yes but arm64 marks all CPUs present even if !ACPI_MADT_ENABLED as we
> don't have the notion of hardware CPU hotplug.
>
> I need to dig some more into the original vCPU hotplug support and why
> we ended up with all CPUs marked as present even if not calling
> register_cpu():
>
> https://lore.kernel.org/linux-arm-kernel/20240529133446.28446-1-Jonathan.Cameron@huawei.com/
>
> What's the MADT GICC provided by qemu with "-smp cpus=4,maxcpus=8"? If
> it says Enabled for the first 4 and Online Capable for the rest, maybe
> we can try something like below:
>
> ----------------------8<-----------------
> diff --git a/arch/arm64/kernel/acpi.c b/arch/arm64/kernel/acpi.c
> index 5891f92c2035..681aa2bbc399 100644
> --- a/arch/arm64/kernel/acpi.c
> +++ b/arch/arm64/kernel/acpi.c
> @@ -448,12 +448,14 @@ int acpi_map_cpu(acpi_handle handle, phys_cpuid_t physid, u32 apci_id,
> return *pcpu;
> }
>
> + set_cpu_present(*pcpu, true);
> return 0;
> }
> EXPORT_SYMBOL(acpi_map_cpu);
>
> int acpi_unmap_cpu(int cpu)
> {
> + set_cpu_present(cpu, false);
> return 0;
> }
> EXPORT_SYMBOL(acpi_unmap_cpu);
> diff --git a/arch/arm64/kernel/smp.c b/arch/arm64/kernel/smp.c
> index 1aa324104afb..6421027669fc 100644
> --- a/arch/arm64/kernel/smp.c
> +++ b/arch/arm64/kernel/smp.c
> @@ -566,6 +566,11 @@ struct acpi_madt_generic_interrupt *acpi_cpu_get_madt_gicc(int cpu)
> }
> EXPORT_SYMBOL_GPL(acpi_cpu_get_madt_gicc);
>
> +static bool acpi_cpu_is_present(int cpu)
> +{
> + return acpi_cpu_get_madt_gicc(cpu)->flags & ACPI_MADT_ENABLED;
> +}
> +
> /*
> * acpi_map_gic_cpu_interface - parse processor MADT entry
> *
> @@ -670,6 +675,11 @@ static void __init acpi_parse_and_init_cpus(void)
> early_map_cpu_to_node(i, acpi_numa_get_nid(i));
> }
> #else
> +static bool acpi_cpu_is_present(int cpu)
> +{
> + return false;
> +}
> +
> #define acpi_parse_and_init_cpus(...) do { } while (0)
> #endif
>
> @@ -808,7 +818,8 @@ void __init smp_prepare_cpus(unsigned int max_cpus)
> if (err)
> continue;
>
> - set_cpu_present(cpu, true);
> + if (acpi_disabled || acpi_cpu_is_present(cpu))
> + set_cpu_present(cpu, true);
Hi, Catalin
It alss passes the test on the local QEMU-KVM environment where the ACPI
issue occurs. And this looks like the cleanest fix.
Best regards,
Jinjie
> numa_store_cpu_info(cpu);
> }
> }
>
^ permalink raw reply
* Re: [PATCH v3 02/11] iommu: Pass in reset result to pci_dev_reset_iommu_done()
From: Nicolin Chen @ 2026-04-24 2:46 UTC (permalink / raw)
To: Baolu Lu
Cc: Will Deacon, Robin Murphy, Joerg Roedel, Bjorn Helgaas,
Jason Gunthorpe, Rafael J . Wysocki, Len Brown,
Pranjal Shrivastava, Mostafa Saleh, Kevin Tian, linux-arm-kernel,
iommu, linux-kernel, linux-acpi, linux-pci, vsethi, Shuai Xue
In-Reply-To: <c8c8b482-3781-4d33-9aea-866467d15b69@linux.intel.com>
On Fri, Apr 24, 2026 at 10:38:09AM +0800, Baolu Lu wrote:
> On 4/17/26 07:28, Nicolin Chen wrote:
> > @@ -4083,6 +4093,18 @@ void pci_dev_reset_iommu_done(struct pci_dev *pdev)
> > if (WARN_ON(!group->blocking_domain))
> > return;
> > + /*
> > + * A reset failure implies that the device might be unreliable. E.g. its
> > + * device cache might retain stale entries, which potentially results in
> > + * memory corruption. Thus, do not unblock the device until a successful
> > + * reset.
> > + */
> > + if (!reset_succeeds) {
> > + pci_err(pdev,
> > + "Reset failed. Keep it blocked to protect memory\n");
> > + return;
> > + }
>
> Nit: pci_dev_reset_iommu_done() does nothing if reset_succeeds is false.
> Would it be better to handle this in the caller instead? Something like:
>
> if (reset_succeeds)
> pci_dev_reset_iommu_done(dev);
>
> ?
It would also need a print and some duplicated comments. Actually,
that would be my v2, which Kevin suggested this against:
https://lore.kernel.org/all/BN9PR11MB5276706AE4E0BBE86F0F6E158C4EA@BN9PR11MB5276.namprd11.prod.outlook.com/
Though I don't have a strong personal reference here, I do see this
version slightly cleaner than doing in the callers.
Thanks
Nicolin
^ permalink raw reply
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox