Пример #1
0
static int marimba_adie_codec_enable_sidetone(
    struct adie_codec_path *rx_path_ptr,
    u32 enable)
{
    int rc = 0;

    pr_debug("%s()\n", __func__);

    mutex_lock(&adie_codec.lock);

    if (!rx_path_ptr || &adie_codec.path[ADIE_CODEC_RX] != rx_path_ptr) {
        pr_err("%s: invalid path pointer\n", __func__);
        rc = -EINVAL;
        goto error;
    } else if (rx_path_ptr->curr_stage !=
               ADIE_CODEC_DIGITAL_ANALOG_READY) {
        pr_err("%s: bad state\n", __func__);
        rc = -EPERM;
        goto error;
    }

    if (enable)
        rc = adie_codec_write(MARIMBA_CDC_RX_CTL,
                              MARIMBA_CDC_RX_CTL_ST_EN_MASK,
                              (0x1 << MARIMBA_CDC_RX_CTL_ST_EN_SHFT));
    else
        rc = adie_codec_write(MARIMBA_CDC_RX_CTL,
                              MARIMBA_CDC_RX_CTL_ST_EN_MASK, 0);

error:
    mutex_unlock(&adie_codec.lock);
    return rc;
}
Пример #2
0
static void marimba_codec_bring_down(void)
{
    adie_codec_write(0xFF, 0xFF, 0x07);
    adie_codec_write(0xFF, 0xFF, 0x06);
    adie_codec_write(0xFF, 0xFF, 0x0e);
    adie_codec_write(0xFF, 0xFF, 0x08);
    adie_codec_write(0x03, 0xFF, 0x00);
}
Пример #3
0
static ssize_t codec_debug_write(struct file *filp,
                                 const char __user *ubuf, size_t cnt, loff_t *ppos)
{
    char *access_str = filp->private_data;
    char lbuf[32];
    int rc;
    long int param[5];

    if (cnt > sizeof(lbuf) - 1)
        return -EINVAL;

    rc = copy_from_user(lbuf, ubuf, cnt);
    if (rc)
        return -EFAULT;

    lbuf[cnt] = '\0';

    if (!strcmp(access_str, "power")) {
        if (get_parameters(lbuf, param, 1) == 0) {
            switch (param[0]) {
            case 1:
                adie_codec.codec_pdata->marimba_codec_power(1);
                marimba_codec_bring_up();
                break;
            case 0:
                marimba_codec_bring_down();
                adie_codec.codec_pdata->marimba_codec_power(0);
                break;
            default:
                rc = -EINVAL;
                break;
            }
        } else
            rc = -EINVAL;
    } else if (!strcmp(access_str, "poke")) {
        /* write */
        rc = get_parameters(lbuf, param, 2);
        if ((param[0] <= 0xFF) && (param[1] <= 0xFF) &&
                (rc == 0))
            adie_codec_write(param[0], 0xFF, param[1]);
        else
            rc = -EINVAL;
    } else if (!strcmp(access_str, "peek")) {
        /* read */
        rc = get_parameters(lbuf, param, 1);
        if ((param[0] <= 0xFF) && (rc == 0))
            adie_codec_read(param[0], &read_data);
        else
            rc = -EINVAL;
    }

    if (rc == 0)
        rc = cnt;
    else
        pr_err("%s: rc = %d\n", __func__, rc);

    return rc;
}
Пример #4
0
static void marimba_codec_bring_up(void)
{
    /* bring up sequence for Marimba codec core
     * ensure RESET_N = 0 and GDFS_CLAMP_EN=1 -
     * set GDFS_EN_FEW=1 then GDFS_EN_REST=1 then
     * GDFS_CLAMP_EN = 0 and finally RESET_N = 1
     * Marimba codec bring up should use the Marimba
     * slave address after which the codec slave
     * address can be used
     */

    /* Bring up codec */
    adie_codec_write(0xFF, 0xFF, 0x08);

    /* set GDFS_EN_FEW=1 */
    adie_codec_write(0xFF, 0xFF, 0x0a);

    /* set GDFS_EN_REST=1 */
    adie_codec_write(0xFF, 0xFF, 0x0e);

    /* set RESET_N=1 */
    adie_codec_write(0xFF, 0xFF, 0x07);

    adie_codec_write(0xFF, 0xFF, 0x17);

    /* enable band gap */
    adie_codec_write(0x03, 0xFF, 0x04);

    /* dither delay selected and dmic gain stage bypassed */
    adie_codec_write(0x8F, 0xFF, 0x44);
}
Пример #5
0
int adie_codec_close(struct adie_codec_path *path_ptr)
{
	int rc = 0;

	mutex_lock(&adie_codec.lock);

	if (!path_ptr) {
		rc = -EINVAL;
		goto error;
	}
	if (path_ptr->curr_stage != ADIE_CODEC_DIGITAL_OFF)
		adie_codec_proceed_stage(path_ptr, ADIE_CODEC_DIGITAL_OFF);

	BUG_ON(!adie_codec.ref_cnt);

	path_ptr->profile = NULL;
	adie_codec.ref_cnt--;

	if (!adie_codec.ref_cnt) {

		adie_codec_write(0xFF, 0xFF, 0x07);
		adie_codec_write(0xFF, 0xFF, 0x06);
		adie_codec_write(0xFF, 0xFF, 0x0e);
		adie_codec_write(0xFF, 0xFF, 0x08);
		adie_codec_write(0x03, 0xFF, 0x00);

		if (adie_codec.codec_pdata &&
				adie_codec.codec_pdata->marimba_codec_power) {

			rc = adie_codec.codec_pdata->marimba_codec_power(0);
			if (rc) {
				pr_aud_err("%s: could not power down marimba "
						"codec\n", __func__);
				goto error;
			}
		}
	}
error:
	mutex_unlock(&adie_codec.lock);
	return rc;
}
Пример #6
0
static void adie_codec_reach_stage_action(struct adie_codec_path *path_ptr,
        u32 stage)
{
    u32 iter;
    struct adie_codec_register *reg_info;

    if (stage == ADIE_CODEC_FLASH_IMAGE) {
        /* perform reimage */
        for (iter = 0; iter < path_ptr->img.img_sz; iter++) {
            reg_info = &path_ptr->img.regs[iter];
            adie_codec_write(reg_info->reg,
                             reg_info->mask, reg_info->val);
        }
    }
}
Пример #7
0
static int marimba_adie_codec_proceed_stage(struct adie_codec_path *path_ptr,
        u32 state)
{
    int rc = 0, loop_exit = 0;
    struct adie_codec_action_unit *curr_action;
    struct adie_codec_hwsetting_entry *setting;
    u8 reg, mask, val;

    mutex_lock(&adie_codec.lock);
    setting = &path_ptr->profile->settings[path_ptr->hwsetting_idx];
    while (!loop_exit) {
        curr_action = &setting->actions[path_ptr->stage_idx];
        switch (curr_action->type) {
        case ADIE_CODEC_ACTION_ENTRY:
            ADIE_CODEC_UNPACK_ENTRY(curr_action->action,
                                    reg, mask, val);
            adie_codec_write(reg, mask, val);
            break;
        case ADIE_CODEC_ACTION_DELAY_WAIT:
            if (curr_action->action > MAX_MDELAY_US)
                msleep(curr_action->action/1000);
            else if (curr_action->action < MIN_MDELAY_US)
                udelay(curr_action->action);
            else
                mdelay(curr_action->action/1000);
            break;
        case ADIE_CODEC_ACTION_STAGE_REACHED:
            adie_codec_reach_stage_action(path_ptr,
                                          curr_action->action);
            if (curr_action->action == state) {
                path_ptr->curr_stage = state;
                loop_exit = 1;
            }
            break;
        default:
            BUG();
        }

        path_ptr->stage_idx++;
        if (path_ptr->stage_idx == setting->action_sz)
            path_ptr->stage_idx = 0;
    }
    mutex_unlock(&adie_codec.lock);
    return rc;
}
Пример #8
0
static int adie_codec_set_dig_vol(enum adie_vol_type vol_type, u32 chan_index,
                                  u32 cur_index, u32 target_index)
{
    u32 count;
    u8 reg, mask, val;
    u32 i;
    u32 index;
    u32 index_jump;

    int rc;

    index_jump = adie_codec_vol_cntrl[vol_type].jump_length;

    reg =
        adie_codec_vol_cntrl[vol_type].
        ch_vol_cntrl_info[chan_index].codec_reg;

    mask =
        adie_codec_vol_cntrl[vol_type].
        ch_vol_cntrl_info[chan_index].codec_mask;

    /* compare the target index with current index */
    if (cur_index < target_index) {

        /* Volume is being increased loop and increase it in 4-5 steps
         */
        count = ((target_index - cur_index) * 100 / index_jump);
        index = cur_index;

        for (i = 1; i <= count; i++) {
            index = index + (int)(index_jump / 100);

            val =
                adie_codec_vol_cntrl[vol_type].ch_vol_cntrl_info
                [chan_index].vol_cntrl_data[index];

            pr_debug("%s: write reg %x val 0x%x\n",
                     __func__, reg, val);

            rc = adie_codec_write(reg, mask, val);
            if (rc < 0) {
                pr_err("%s: write reg %x val 0x%x failed\n",
                       __func__, reg, val);
                return rc;
            }
        }

        /*do one final write to take it to the target index level */
        val =
            adie_codec_vol_cntrl[vol_type].ch_vol_cntrl_info
            [chan_index].vol_cntrl_data[target_index];

        pr_debug("%s: write reg %x val 0x%x\n", __func__, reg, val);

        rc = adie_codec_write(reg, mask, val);

        if (rc < 0) {
            pr_err("%s: write reg %x val 0x%x failed\n",
                   __func__, reg, val);
            return rc;
        }

    } else {

        /* Volume is being decreased from the current setting */
        index = cur_index;
        /* loop and decrease it in 4-5 steps */
        count = ((cur_index - target_index) * 100 / index_jump);

        for (i = 1; i <= count; i++) {
            index = index - (int)(index_jump / 100);

            val =
                adie_codec_vol_cntrl[vol_type].ch_vol_cntrl_info
                [chan_index].vol_cntrl_data[index];

            pr_debug("%s: write reg %x val 0x%x\n",
                     __func__, reg, val);

            rc = adie_codec_write(reg, mask, val);
            if (rc < 0) {
                pr_err("%s: write reg %x val 0x%x failed\n",
                       __func__, reg, val);
                return rc;
            }
        }

        /* do one final write to take it to the target index level */
        val =
            adie_codec_vol_cntrl[vol_type].ch_vol_cntrl_info
            [chan_index].vol_cntrl_data[target_index];

        pr_debug("%s: write reg %x val 0x%x\n", __func__, reg, val);

        rc = adie_codec_write(reg, mask, val);

        if (rc < 0) {
            pr_err("%s: write reg %x val 0x%x failed\n",
                   __func__, reg, val);
            return rc;
        }
    }
    return 0;
}
Пример #9
0
int usb_headset_adie_enable(int enable)
{
	int rc = 0;
	mutex_lock(&adie_codec.lock);
	if (!adie_codec.ref_cnt && enable) {

		if (adie_codec.codec_pdata &&
				adie_codec.codec_pdata->marimba_codec_power) {

			rc = adie_codec.codec_pdata->marimba_codec_power(1);
			if (rc) {
				pr_aud_err("%s: could not power up marimba "
						"codec\n", __func__);
				goto error;
			}
		}

		/* bring up sequence for Marimba codec core
		 * ensure RESET_N = 0 and GDFS_CLAMP_EN=1 -
		 * set GDFS_EN_FEW=1 then GDFS_EN_REST=1 then
		 * GDFS_CLAMP_EN = 0 and finally RESET_N = 1
		 * Marimba codec bring up should use the Marimba
		 * slave address after which the codec slave
		 * address can be used
		 */

		/* Bring up codec */
		adie_codec_write(0xFF, 0xFF, 0x08);
		/* set GDFS_EN_FEW=1 */
		adie_codec_write(0xFF, 0xFF, 0x0a);
		/* set GDFS_EN_REST=1 */
		adie_codec_write(0xFF, 0xFF, 0x0e);
		/* set RESET_N=1 */
		adie_codec_write(0xFF, 0xFF, 0x07);
		adie_codec_write(0xFF, 0xFF, 0x17);
		/* enable band gap */
		adie_codec_write(0x03, 0xFF, 0x04);
		/* dither delay selected and dmic gain stage bypassed */
		adie_codec_write(0x8F, 0xFF, 0x44);
		/* usb audio adie parameter */

		adie_codec_write(0x8a, 0xFF, 0x03);
		adie_codec_write(0x83, 0xFF, 0x00);
		adie_codec_write(0x33, 0xFF, 0x8f);
		mdelay(30);
		adie_codec.usb_state = 1;
		adie_codec.ref_cnt++;
		pr_aud_err("usb adie enabled\n");
	} else if (enable) {
		adie_codec.ref_cnt++;
		adie_codec.usb_state = 1;
	} else if (!enable && adie_codec.ref_cnt > 1) {
		adie_codec.ref_cnt--;
		adie_codec.usb_state = 0;
	} else if (!enable && adie_codec.ref_cnt == 1) {
		adie_codec.ref_cnt = 0;
		adie_codec.usb_state = 0;
		adie_codec_write(0x8a, 0x03, 0x03);
		adie_codec_write(0x33, 0xFF, 0x03);
		adie_codec_write(0x33, 0xFF, 0x00);
		adie_codec_write(0xFF, 0xFF, 0x07);
		adie_codec_write(0xFF, 0xFF, 0x06);
		adie_codec_write(0xFF, 0xFF, 0x0e);
		adie_codec_write(0xFF, 0xFF, 0x08);
		adie_codec_write(0x03, 0xFF, 0x00);

		if (adie_codec.codec_pdata &&
				adie_codec.codec_pdata->marimba_codec_power) {

			rc = adie_codec.codec_pdata->marimba_codec_power(0);
			if (rc) {
				pr_aud_err("%s: could not power down marimba "
						"codec\n", __func__);
				goto error;
			}
		}
		pr_aud_err("usb headset adie disabled");
	}
error:
	mutex_unlock(&adie_codec.lock);
	return rc;
}
Пример #10
0
int adie_codec_open(struct adie_codec_dev_profile *profile,
	struct adie_codec_path **path_pptr)
{
	int rc = 0;

	mutex_lock(&adie_codec.lock);

	if (!profile || !path_pptr) {
		rc = -EINVAL;
		goto error;
	}

	if (adie_codec.path[profile->path_type].profile) {
		rc = -EBUSY;
		goto error;
	}

	if (!adie_codec.ref_cnt) {

		if (adie_codec.codec_pdata &&
				adie_codec.codec_pdata->marimba_codec_power) {

			rc = adie_codec.codec_pdata->marimba_codec_power(1);
			if (rc) {
				pr_aud_err("%s: could not power up marimba "
						"codec\n", __func__);
				goto error;
			}
		}

		/* bring up sequence for Marimba codec core
		 * ensure RESET_N = 0 and GDFS_CLAMP_EN=1 -
		 * set GDFS_EN_FEW=1 then GDFS_EN_REST=1 then
		 * GDFS_CLAMP_EN = 0 and finally RESET_N = 1
		 * Marimba codec bring up should use the Marimba
		 * slave address after which the codec slave
		 * address can be used
		 */

		/* Bring up codec */
		adie_codec_write(0xFF, 0xFF, 0x08);

		/* set GDFS_EN_FEW=1 */
		adie_codec_write(0xFF, 0xFF, 0x0a);

		/* set GDFS_EN_REST=1 */
		adie_codec_write(0xFF, 0xFF, 0x0e);

		/* set RESET_N=1 */
		adie_codec_write(0xFF, 0xFF, 0x07);

		adie_codec_write(0xFF, 0xFF, 0x17);

		/* enable band gap */
		adie_codec_write(0x03, 0xFF, 0x04);

		/* dither delay selected and dmic gain stage bypassed */
		adie_codec_write(0x8F, 0xFF, 0x44);

	}

	adie_codec.path[profile->path_type].profile = profile;
	*path_pptr = (void *) &adie_codec.path[profile->path_type];
	adie_codec.ref_cnt++;
	adie_codec.path[profile->path_type].hwsetting_idx = 0;
	adie_codec.path[profile->path_type].curr_stage = ADIE_CODEC_FLASH_IMAGE;
	adie_codec.path[profile->path_type].stage_idx = 0;


error:

	mutex_unlock(&adie_codec.lock);
	return rc;
}