diff options
-rw-r--r-- | Documentation/devicetree/bindings/sound/fsl,rpmsg-i2s.txt | 1 | ||||
-rw-r--r-- | sound/soc/fsl/fsl_rpmsg_i2s.c | 115 | ||||
-rw-r--r-- | sound/soc/fsl/fsl_rpmsg_i2s.h | 49 |
3 files changed, 116 insertions, 49 deletions
diff --git a/Documentation/devicetree/bindings/sound/fsl,rpmsg-i2s.txt b/Documentation/devicetree/bindings/sound/fsl,rpmsg-i2s.txt index f38cf9d90500..fd62b0d444a8 100644 --- a/Documentation/devicetree/bindings/sound/fsl,rpmsg-i2s.txt +++ b/Documentation/devicetree/bindings/sound/fsl,rpmsg-i2s.txt @@ -7,6 +7,7 @@ serial interfaces with frame synchronization such as I2S. Required properties: - compatible : Compatible list, contains "fsl,imx7ulp-rpmsg-i2s". + "fsl,imx8mq-rpmsg-i2s" - fsl,audioindex : This is an index indicating the audio device index in the M4 side. diff --git a/sound/soc/fsl/fsl_rpmsg_i2s.c b/sound/soc/fsl/fsl_rpmsg_i2s.c index ec3560d3c60c..4d004a3f41ae 100644 --- a/sound/soc/fsl/fsl_rpmsg_i2s.c +++ b/sound/soc/fsl/fsl_rpmsg_i2s.c @@ -30,10 +30,10 @@ SNDRV_PCM_RATE_48000) #define FSL_RPMSG_I2S_FORMATS SNDRV_PCM_FMTBIT_S16_LE -static int i2s_send_message(struct i2s_rpmsg_s *msg, +static int i2s_send_message(struct i2s_rpmsg *msg, struct i2s_info *info) { - int err; + int err = 0; mutex_lock(&info->tx_lock); if (!info->rpdev) { @@ -42,10 +42,12 @@ static int i2s_send_message(struct i2s_rpmsg_s *msg, return -EINVAL; } - dev_dbg(&info->rpdev->dev, "send cmd %d\n", msg->header.cmd); + dev_dbg(&info->rpdev->dev, "send cmd %d\n", msg->send_msg.header.cmd); - reinit_completion(&info->cmd_complete); - err = rpmsg_send(info->rpdev->ept, (void *)msg, + if (!(msg->send_msg.header.type == I2S_TYPE_C)) + reinit_completion(&info->cmd_complete); + + err = rpmsg_send(info->rpdev->ept, (void *)&msg->send_msg, sizeof(struct i2s_rpmsg_s)); if (err) { dev_err(&info->rpdev->dev, "rpmsg_send failed: %d\n", err); @@ -53,20 +55,25 @@ static int i2s_send_message(struct i2s_rpmsg_s *msg, return err; } - /* wait response from rpmsg */ - err = wait_for_completion_timeout(&info->cmd_complete, + if (!(msg->send_msg.header.type == I2S_TYPE_C)) { + /* wait response from rpmsg */ + err = wait_for_completion_timeout(&info->cmd_complete, msecs_to_jiffies(RPMSG_TIMEOUT)); - if (!err) { - dev_err(&info->rpdev->dev, "rpmsg_send cmd %d timeout!\n", - msg->header.cmd); - mutex_unlock(&info->tx_lock); - return -ETIMEDOUT; + if (!err) { + dev_err(&info->rpdev->dev, + "rpmsg_send cmd %d timeout!\n", + msg->send_msg.header.cmd); + mutex_unlock(&info->tx_lock); + return -ETIMEDOUT; + } + memcpy(&msg->recv_msg, &info->recv_msg, + sizeof(struct i2s_rpmsg_r)); + memcpy(&info->rpmsg[msg->recv_msg.header.cmd].recv_msg, + &msg->recv_msg, sizeof(struct i2s_rpmsg_r)); } - if (msg->header.cmd == GET_CODEC_VALUE) - msg->param.buffer_size = info->recv_msg.param.reg_data; - - dev_dbg(&info->rpdev->dev, "cmd:%d, resp %d\n", msg->header.cmd, + dev_dbg(&info->rpdev->dev, "cmd:%d, resp %d\n", + msg->send_msg.header.cmd, info->recv_msg.param.resp); mutex_unlock(&info->tx_lock); @@ -99,6 +106,7 @@ static const struct snd_soc_component_driver fsl_component = { static const struct of_device_id fsl_rpmsg_i2s_ids[] = { { .compatible = "fsl,imx7ulp-rpmsg-i2s"}, + { .compatible = "fsl,imx8mq-rpmsg-i2s"}, { /* sentinel */ } }; MODULE_DEVICE_TABLE(of, fsl_rpmsg_i2s_ids); @@ -149,17 +157,56 @@ static int fsl_rpmsg_i2s_probe(struct platform_device *pdev) i2s_info->work_list[i].i2s_info = i2s_info; } - for (i = 0; i < RPMSG_AUDIO_NUM; i++) { - i2s_info->send_msg[i].header.cate = IMX_RPMSG_AUDIO; - i2s_info->send_msg[i].header.major = IMX_RMPSG_MAJOR; - i2s_info->send_msg[i].header.minor = IMX_RMPSG_MINOR; - i2s_info->send_msg[i].header.type = I2S_TYPE_A; - i2s_info->send_msg[i].param.audioindex = audioindex; + for (i = 0; i < I2S_CMD_MAX_NUM ; i++) { + i2s_info->rpmsg[i].send_msg.header.cate = IMX_RPMSG_AUDIO; + i2s_info->rpmsg[i].send_msg.header.major = IMX_RMPSG_MAJOR; + i2s_info->rpmsg[i].send_msg.header.minor = IMX_RMPSG_MINOR; + i2s_info->rpmsg[i].send_msg.header.type = I2S_TYPE_A; + i2s_info->rpmsg[i].send_msg.param.audioindex = audioindex; } mutex_init(&i2s_info->tx_lock); mutex_init(&i2s_info->i2c_lock); + if (of_device_is_compatible(pdev->dev.of_node, + "fsl,imx7ulp-rpmsg-i2s")) { + rpmsg_i2s->codec = 1; + rpmsg_i2s->version = 1; + rpmsg_i2s->rates = SNDRV_PCM_RATE_8000 | + SNDRV_PCM_RATE_16000 | + SNDRV_PCM_RATE_48000; + rpmsg_i2s->formats = SNDRV_PCM_FMTBIT_S16_LE; + fsl_rpmsg_i2s_dai.playback.rates = rpmsg_i2s->rates; + fsl_rpmsg_i2s_dai.playback.formats = rpmsg_i2s->formats; + fsl_rpmsg_i2s_dai.capture.rates = rpmsg_i2s->rates; + fsl_rpmsg_i2s_dai.capture.formats = rpmsg_i2s->formats; + } + + if (of_device_is_compatible(pdev->dev.of_node, + "fsl,imx8mq-rpmsg-i2s")) { + rpmsg_i2s->codec = 0; + rpmsg_i2s->version = 2; + rpmsg_i2s->rates = SNDRV_PCM_RATE_32000 | + SNDRV_PCM_RATE_48000 | + SNDRV_PCM_RATE_96000 | + SNDRV_PCM_RATE_192000; + rpmsg_i2s->formats = SNDRV_PCM_FMTBIT_S16_LE | + SNDRV_PCM_FMTBIT_S24_LE | + SNDRV_PCM_FMTBIT_S32_LE | + SNDRV_PCM_FMTBIT_S24_3LE; + fsl_rpmsg_i2s_dai.playback.rates = rpmsg_i2s->rates; + fsl_rpmsg_i2s_dai.playback.formats = rpmsg_i2s->formats; + fsl_rpmsg_i2s_dai.capture.rates = rpmsg_i2s->rates; + fsl_rpmsg_i2s_dai.capture.formats = rpmsg_i2s->formats; + } + + if (of_property_read_bool(pdev->dev.of_node, "fsl,enable-lpa")) + rpmsg_i2s->enable_lpa = 1; + + if (of_property_read_u32(np, "fsl,dma-buffer-size", + &i2s_info->prealloc_buffer_size)) + i2s_info->prealloc_buffer_size = IMX_DEFAULT_DMABUF_SIZE; + platform_set_drvdata(pdev, rpmsg_i2s); pm_runtime_enable(&pdev->dev); @@ -205,17 +252,17 @@ static int fsl_rpmsg_i2s_suspend(struct device *dev) { struct fsl_rpmsg_i2s *rpmsg_i2s = dev_get_drvdata(dev); struct i2s_info *i2s_info = &rpmsg_i2s->i2s_info; - struct i2s_rpmsg_s *rpmsg_tx; - struct i2s_rpmsg_s *rpmsg_rx; + struct i2s_rpmsg *rpmsg_tx; + struct i2s_rpmsg *rpmsg_rx; flush_workqueue(i2s_info->rpmsg_wq); - rpmsg_tx = &i2s_info->send_msg[SNDRV_PCM_STREAM_PLAYBACK]; - rpmsg_rx = &i2s_info->send_msg[SNDRV_PCM_STREAM_CAPTURE]; + rpmsg_tx = &i2s_info->rpmsg[I2S_TX_SUSPEND]; + rpmsg_rx = &i2s_info->rpmsg[I2S_RX_SUSPEND]; - rpmsg_tx->header.cmd = I2S_TX_SUSPEND; + rpmsg_tx->send_msg.header.cmd = I2S_TX_SUSPEND; i2s_send_message(rpmsg_tx, i2s_info); - rpmsg_rx->header.cmd = I2S_RX_SUSPEND; + rpmsg_rx->send_msg.header.cmd = I2S_RX_SUSPEND; i2s_send_message(rpmsg_rx, i2s_info); return 0; @@ -225,16 +272,16 @@ static int fsl_rpmsg_i2s_resume(struct device *dev) { struct fsl_rpmsg_i2s *rpmsg_i2s = dev_get_drvdata(dev); struct i2s_info *i2s_info = &rpmsg_i2s->i2s_info; - struct i2s_rpmsg_s *rpmsg_tx; - struct i2s_rpmsg_s *rpmsg_rx; + struct i2s_rpmsg *rpmsg_tx; + struct i2s_rpmsg *rpmsg_rx; - rpmsg_tx = &i2s_info->send_msg[SNDRV_PCM_STREAM_PLAYBACK]; - rpmsg_rx = &i2s_info->send_msg[SNDRV_PCM_STREAM_CAPTURE]; + rpmsg_tx = &i2s_info->rpmsg[I2S_TX_RESUME]; + rpmsg_rx = &i2s_info->rpmsg[I2S_RX_RESUME]; - rpmsg_tx->header.cmd = I2S_TX_RESUME; + rpmsg_tx->send_msg.header.cmd = I2S_TX_RESUME; i2s_send_message(rpmsg_tx, i2s_info); - rpmsg_rx->header.cmd = I2S_RX_RESUME; + rpmsg_rx->send_msg.header.cmd = I2S_RX_RESUME; i2s_send_message(rpmsg_rx, i2s_info); return 0; diff --git a/sound/soc/fsl/fsl_rpmsg_i2s.h b/sound/soc/fsl/fsl_rpmsg_i2s.h index cbb984e07999..9c5105c0ecf6 100644 --- a/sound/soc/fsl/fsl_rpmsg_i2s.h +++ b/sound/soc/fsl/fsl_rpmsg_i2s.h @@ -304,11 +304,20 @@ #define I2S_RX_RESUME 0x13 #define SET_CODEC_VALUE 0x14 #define GET_CODEC_VALUE 0x15 -#define WORK_MAX_NUM 0x16 +#define I2S_TX_POINTER 0x16 +#define I2S_RX_POINTER 0x17 + +#define I2S_TYPE_A_NUM 0x18 + +#define WORK_MAX_NUM 0x18 #define I2S_TX_PERIOD_DONE 0x0 #define I2S_RX_PERIOD_DONE 0x1 +#define I2S_TYPE_C_NUM 0x2 + +#define I2S_CMD_MAX_NUM (I2S_TYPE_A_NUM + I2S_TYPE_C_NUM) + #define I2S_TYPE_A 0x0 #define I2S_TYPE_B 0x1 #define I2S_TYPE_C 0x2 @@ -320,6 +329,7 @@ #define RPMSG_S16_LE 0x0 #define RPMSG_S24_LE 0x1 +#define RPMSG_S32_LE 0x2 #define RPMSG_CH_LEFT 0x0 #define RPMSG_CH_RIGHT 0x1 @@ -339,10 +349,12 @@ struct i2s_param_s { struct i2s_param_r { unsigned char audioindex; unsigned char resp; - unsigned char reserved1[5]; + unsigned char reserved1[1]; + unsigned int buffer_offset; /* the consumed offset of buffer*/ unsigned int reg_addr; unsigned int reg_data; - unsigned char reserved2[8]; + unsigned char reserved2[4]; + unsigned int buffer_tail; } __packed; /* struct of send message */ @@ -357,46 +369,53 @@ struct i2s_rpmsg_r { struct i2s_param_r param; }; +struct i2s_rpmsg { + struct i2s_rpmsg_s send_msg; + struct i2s_rpmsg_r recv_msg; +}; + struct work_of_rpmsg { struct i2s_info *i2s_info; /* sent msg for each work */ - struct i2s_rpmsg_s msg; + struct i2s_rpmsg msg; struct work_struct work; }; -enum { - RPMSG_AUDIO_TX = 0, - RPMSG_AUDIO_RX = 1, - RPMSG_AUDIO_I2C = 2, - RPMSG_AUDIO_NUM = 3, -}; - typedef void (*dma_callback)(void *arg); struct i2s_info { struct rpmsg_device *rpdev; struct device *dev; struct completion cmd_complete; - /* received msg */ + + /* received msg (global) */ struct i2s_rpmsg_r recv_msg; - /* backup sent msg */ - struct i2s_rpmsg_s send_msg[RPMSG_AUDIO_NUM]; + + struct i2s_rpmsg rpmsg[I2S_CMD_MAX_NUM]; struct workqueue_struct *rpmsg_wq; struct work_of_rpmsg work_list[WORK_MAX_NUM]; int work_index; int num_period[2]; void *callback_param[2]; - int (*send_message)(struct i2s_rpmsg_s *msg, struct i2s_info *info); + int (*send_message)(struct i2s_rpmsg *msg, struct i2s_info *info); dma_callback callback[2]; spinlock_t lock[2]; struct mutex tx_lock; struct mutex i2c_lock; + struct timer_list stream_timer[2]; + int prealloc_buffer_size; }; struct fsl_rpmsg_i2s { struct platform_device *pdev; struct i2s_info i2s_info; struct pm_qos_request pm_qos_req; + int codec; + int force_lpa; + int version; + int rates; + u64 formats; + int enable_lpa; }; #define RPMSG_CODEC_DRV_NAME "rpmsg-audio-codec" |