MLK-16545-2: ASoC: fsl_hifi4: add support to reset hifi4 codec
authorWeiguang Kong <weiguang.kong@nxp.com>
Thu, 28 Sep 2017 04:49:49 +0000 (12:49 +0800)
committerNitin Garg <nitin.garg@nxp.com>
Mon, 19 Mar 2018 20:38:45 +0000 (15:38 -0500)
add cases to support resetting the hifi4 codec when receiving
HIFI4_RESET_CODEC command from the user space.

Signed-off-by: Weiguang Kong <weiguang.kong@nxp.com>
Reviewed-by: Daniel Baluta <daniel.baluta@nxp.com>
sound/soc/fsl/fsl_hifi4.c
sound/soc/fsl/fsl_hifi4.h

index def93c2..cc8195f 100644 (file)
@@ -1366,6 +1366,58 @@ static int fsl_hifi4_codec_close(struct fsl_hifi4 *hifi4_priv,
        return ret;
 }
 
+static int fsl_hifi4_codec_reset(struct fsl_hifi4 *hifi4_priv,
+                                                       void __user *user)
+{
+       struct device *dev = hifi4_priv->dev;
+       union icm_header_t apu_icm;
+       struct icm_cdc_iobuf_t *codec_iobuf_info =
+                               &hifi4_priv->codec_iobuf_info;
+       int id;
+       long err = 0;
+       unsigned long ret = 0;
+
+       ret = copy_from_user(&id, user, sizeof(int));
+       if (ret) {
+               dev_err(dev, "failed to get para from user space\n");
+               return -EFAULT;
+       }
+
+       if (hifi4_priv->process_id != id) {
+               err = switch_codec(hifi4_priv, id);
+               if (err) {
+                       dev_err(dev, "failed to switch codec in codec reset\n");
+                       return err;
+               }
+       }
+
+       init_completion(&hifi4_priv->cmd_complete);
+       hifi4_priv->is_done = 0;
+
+       apu_icm.allbits = 0;    /* clear all bits;*/
+       apu_icm.ack = 0;
+       apu_icm.intr = 1;
+       apu_icm.msg = ICM_RESET;
+       apu_icm.size = 0;
+       icm_intr_send(hifi4_priv, apu_icm.allbits);
+
+       /* wait for response here */
+       err = icm_ack_wait(hifi4_priv, apu_icm.allbits);
+       if (err)
+               return err;
+
+       /* reset codec_iobuf_info */
+       codec_iobuf_info->inp_buf_size_max = 0;
+       codec_iobuf_info->inp_cur_offset = 0;
+
+       codec_iobuf_info->out_buf_size_max = 0;
+       codec_iobuf_info->out_cur_offset   = 0;
+
+       err = hifi4_priv->ret_status;
+
+       return err;
+}
+
 static struct miscdevice hifi4_miscdev = {
        .name   = "mxc_hifi4",
        .minor  = MISC_DYNAMIC_MINOR,
@@ -1409,6 +1461,9 @@ static long fsl_hifi4_ioctl(struct file *file, unsigned int cmd,
        case HIFI4_SET_CONFIG:
                ret = fsl_hifi4_set_config(hifi4_priv, user);
                break;
+       case HIFI4_RESET_CODEC:
+               ret = fsl_hifi4_codec_reset(hifi4_priv, user);
+               break;
        default:
                break;
        }
@@ -1457,6 +1512,9 @@ static long fsl_hifi4_compat_ioctl(struct file *file, unsigned int cmd,
        case HIFI4_SET_CONFIG:
                ret = fsl_hifi4_set_config(hifi4_priv, user);
                break;
+       case HIFI4_RESET_CODEC:
+               ret = fsl_hifi4_codec_reset(hifi4_priv, user);
+               break;
        default:
                break;
        }
@@ -1744,6 +1802,16 @@ int process_act_complete(struct fsl_hifi4 *hifi4_priv, u32 msg)
                }
                break;
 
+       case ICM_RESET:
+               {
+                       struct icm_reset_info_t *ext_msg =
+                               (struct icm_reset_info_t *)pmsg_apu;
+                       hifi4_priv->ret_status = ext_msg->ret;
+                       hifi4_priv->is_done = 1;
+                       complete(&hifi4_priv->cmd_complete);
+               }
+               break;
+
        default:
                ret_val = -1;
                break;
index fa70580..04e52df 100644 (file)
@@ -136,6 +136,7 @@ enum icm_action_t {
        ICM_EXT_MSG_ADDR,
 
        ICM_SWITCH_CODEC,
+       ICM_RESET,
 };
 
 enum aud_status_t {
@@ -152,6 +153,11 @@ struct icm_open_resp_info_t {
        s32 ret;
 };
 
+struct icm_reset_info_t {
+       u32 codec_id;
+       s32 ret;                   /* executed status of reset function */
+};
+
 struct icm_switch_info_t {
        u32 proc_id;    /* audio id */
        u32 status;     /* codec status */