sound/soc/fsl/imx-audio-rpmsg.c

Source file repositories/reference/linux-study-clean/sound/soc/fsl/imx-audio-rpmsg.c

File Facts

System
Linux kernel
Corpus path
sound/soc/fsl/imx-audio-rpmsg.c
Extension
.c
Size
3934 bytes
Lines
146
Domain
Driver Families
Bucket
sound/soc
Inferred role
Driver Families: implementation source
Status
source implementation candidate

Why This File Exists

Repeatable hardware-adapter layer. Deep compatibility for every driver is out of scope; this atlas records patterns, probe lifecycles, bus glue, IRQ/DMA usage, and links back to core abstractions.

Dependency Surface

Detected Declarations

Annotated Snippet

struct imx_audio_rpmsg {
	struct platform_device *rpmsg_pdev;
	struct platform_device *card_pdev;
};

static int imx_audio_rpmsg_cb(struct rpmsg_device *rpdev, void *data, int len,
			      void *priv, u32 src)
{
	struct imx_audio_rpmsg *rpmsg = dev_get_drvdata(&rpdev->dev);
	struct rpmsg_r_msg *r_msg = (struct rpmsg_r_msg *)data;
	struct rpmsg_info *info;
	struct rpmsg_msg *msg;
	unsigned long flags;

	if (!rpmsg->rpmsg_pdev)
		return 0;

	info = platform_get_drvdata(rpmsg->rpmsg_pdev);

	dev_dbg(&rpdev->dev, "get from%d: cmd:%d. %d\n",
		src, r_msg->header.cmd, r_msg->param.resp);

	switch (r_msg->header.type) {
	case MSG_TYPE_C:
		/* TYPE C is notification from M core */
		switch (r_msg->header.cmd) {
		case TX_PERIOD_DONE:
			spin_lock_irqsave(&info->lock[TX], flags);
			msg = &info->msg[TX_PERIOD_DONE + MSG_TYPE_A_NUM];
			msg->r_msg.param.buffer_tail =
						r_msg->param.buffer_tail;
			msg->r_msg.param.buffer_tail %= info->num_period[TX];
			spin_unlock_irqrestore(&info->lock[TX], flags);
			info->callback[TX](info->callback_param[TX]);
			break;
		case RX_PERIOD_DONE:
			spin_lock_irqsave(&info->lock[RX], flags);
			msg = &info->msg[RX_PERIOD_DONE + MSG_TYPE_A_NUM];
			msg->r_msg.param.buffer_tail =
						r_msg->param.buffer_tail;
			msg->r_msg.param.buffer_tail %= info->num_period[1];
			spin_unlock_irqrestore(&info->lock[RX], flags);
			info->callback[RX](info->callback_param[RX]);
			break;
		default:
			dev_warn(&rpdev->dev, "unknown msg command\n");
			break;
		}
		break;
	case MSG_TYPE_B:
		/* TYPE B is response msg */
		memcpy(&info->r_msg, r_msg, sizeof(struct rpmsg_r_msg));
		complete(&info->cmd_complete);
		break;
	default:
		dev_warn(&rpdev->dev, "unknown msg type\n");
		break;
	}

	return 0;
}

static int imx_audio_rpmsg_probe(struct rpmsg_device *rpdev)
{
	struct imx_audio_rpmsg *data;
	int ret = 0;

	dev_info(&rpdev->dev, "new channel: 0x%x -> 0x%x!\n",
		 rpdev->src, rpdev->dst);

	data = devm_kzalloc(&rpdev->dev, sizeof(*data), GFP_KERNEL);
	if (!data)
		return -ENOMEM;

	dev_set_drvdata(&rpdev->dev, data);

	/* Register platform driver for rpmsg routine */
	data->rpmsg_pdev = platform_device_register_data(&rpdev->dev,
							 rpdev->id.name,
							 PLATFORM_DEVID_NONE,
							 NULL, 0);
	if (IS_ERR(data->rpmsg_pdev)) {
		dev_err(&rpdev->dev, "failed to register rpmsg platform.\n");
		ret = PTR_ERR(data->rpmsg_pdev);
	}

	data->card_pdev = platform_device_register_data(&rpdev->dev,
							"imx-audio-rpmsg",
							PLATFORM_DEVID_AUTO,
							rpdev->id.name,

Annotation

Implementation Notes