Ejemplo n.º 1
0
static int cpcap_regulator_enable(struct regulator_dev *rdev)
{
	struct cpcap_device *cpcap = rdev_get_drvdata(rdev);
	int regltr_id;
	int retval;
	enum cpcap_reg regnr;

	regltr_id = rdev_get_id(rdev);
	if (regltr_id >= CPCAP_NUM_REGULATORS)
		return -EINVAL;

	regnr = cpcap_regltr_data[regltr_id].reg;

	retval = cpcap_regacc_write(cpcap, regnr,
				    cpcap_regltr_data[regltr_id].mode_val,
				    cpcap_regltr_data[regltr_id].mode_mask);

	if ((retval == 0) &&
		(cpcap_regltr_data[regltr_id].mode_val & CPCAP_REG_OFF_MODE_SEC)) {
		retval = cpcap_regacc_write(cpcap,
									cpcap_regltr_data[regltr_id].assignment_reg,
									0,
									cpcap_regltr_data[regltr_id].assignment_mask);
	}
	if ((cpcap_regltr_data[regltr_id].turn_on_time) && (retval == 0))
		udelay(cpcap_regltr_data[regltr_id].turn_on_time);

	return retval;
}
Ejemplo n.º 2
0
static int cpcap_regulator_disable(struct regulator_dev *rdev)
{
	struct cpcap_device *cpcap = rdev_get_drvdata(rdev);
	int regltr_id;
	int retval;
	enum cpcap_reg regnr;

	regltr_id = rdev_get_id(rdev);
	if (regltr_id >= CPCAP_NUM_REGULATORS)
		return -EINVAL;

	regnr = cpcap_regltr_data[regltr_id].reg;

	retval = 0;
	if (cpcap_regltr_data[regltr_id].mode_val & CPCAP_REG_OFF_MODE_SEC) {
		retval = cpcap_regacc_write(cpcap,
									cpcap_regltr_data[regltr_id].assignment_reg,
									cpcap_regltr_data[regltr_id].assignment_mask,
									cpcap_regltr_data[regltr_id].assignment_mask);
	}
	if (retval == 0) {
		retval = cpcap_regacc_write(cpcap, regnr,
									cpcap_regltr_data[regltr_id].off_mode_val,
									cpcap_regltr_data[regltr_id].mode_mask);
	}
	return (retval);
}
static void cpcap_gpio_led_set(struct led_classdev *led_cdev,
				enum led_brightness value)
{
	int cpcap_status = 0;

	struct gpio_led_data *gpio_led_data =
	    container_of(led_cdev, struct gpio_led_data,
			 cpcap_gpio_led_class_dev);

	if (debug)
		pr_info("%s %d\n", __func__, value);

	if (value > LED_OFF) {
		cpcap_status = cpcap_regacc_write(gpio_led_data->cpcap,
						  gpio_led_config_data.reg,
						  CPCAP_GPIO_ON,
						  CPCAP_GPIO_ON_OFF_MASK);
	} else {
		cpcap_status = cpcap_regacc_write(gpio_led_data->cpcap,
						  gpio_led_config_data.reg,
						  CPCAP_GPIO_OFF,
						  CPCAP_GPIO_ON_OFF_MASK);
	}

	if (cpcap_status < 0)
		pr_err("%s: Writing to the register failed for %i\n",
		       __func__, cpcap_status);

	return;
}
Ejemplo n.º 4
0
static void logged_cpcap_write(struct cpcap_device *cpcap, unsigned int reg,
			unsigned short int value, unsigned short int mask)
{
	if (mask != 0) {
		int ret_val = 0;
#ifdef CPCAP_AUDIO_SPI_LOG
		printk(KERN_DEBUG
			"CPCAP_AUDIO_SPI_WRITE: reg %u, value 0x%x,mask 0x%x\n",
		       CPCAP_REG_FOR_POWERIC_REG(reg), value, mask);
#endif
		ret_val = cpcap_regacc_write(cpcap, reg, value, mask);
		if (ret_val != 0)
			CPCAP_AUDIO_ERROR_LOG(
				"Write to register %u failed: error %d \n",
				reg, ret_val);
#ifdef CPCAP_AUDIO_SPI_READBACK
		ret_val = cpcap_regacc_read(cpcap, reg, &value);
		if (ret_val == 0)
			printk(KERN_DEBUG
				"CPCAP_AUDIO_SPI_VERIFY reg %u: value 0x%x \n",
				CPCAP_REG_FOR_POWERIC_REG(reg), value);
		else
			printk(KERN_ERR
				"CPCAP_AUDIO_SPI_VERIFY reg %u FAILED\n",
				CPCAP_REG_FOR_POWERIC_REG(reg));
#endif
	}
}
static int cpcap_gpio_led_probe(struct platform_device *pdev)
{
	int ret;
	struct gpio_led_data *info;

	if (pdev == NULL) {
		pr_err("%s: platform device required\n", __func__);
		ret = -ENODEV;
		goto err_pd_or_kzalloc_failed;
	}
	info = kzalloc(sizeof(struct cpcap_gpio_led_config_data), GFP_KERNEL);
	if (info == NULL) {
		ret = -ENOMEM;
		goto err_pd_or_kzalloc_failed;
	}

	if (pdev->dev.platform_data == NULL) {
		pr_err("%s: platform data required\n", __func__);
		ret = -ENODEV;
		goto err_pd_or_kzalloc_failed;
	}
	memcpy(&gpio_led_config_data, pdev->dev.platform_data,
	       sizeof(gpio_led_config_data));

	info->cpcap = platform_get_drvdata(pdev);
	platform_set_drvdata(pdev, info);

	ret = cpcap_regacc_write(info->cpcap,
				 gpio_led_config_data.reg,
				 gpio_led_config_data.init,
				 gpio_led_config_data.init_mask);
	if (ret < 0) {
		pr_err("%s: Writing CPCAP failed:\n", __func__);
		goto err_probe_failed;
	}

	info->cpcap_gpio_led_class_dev.name = gpio_led_config_data.class_name;
	info->cpcap_gpio_led_class_dev.brightness_set = cpcap_gpio_led_set;

	ret = led_classdev_register(&pdev->dev,
				    &info->cpcap_gpio_led_class_dev);
	if (ret < 0) {
		pr_err("%s: Register led class failed:\n", __func__);
		goto err_probe_failed;
	}

	if (debug)
		pr_info("%s successful\n", __func__);

	return ret;

err_probe_failed:
	kfree(info);

err_pd_or_kzalloc_failed:
	if (debug)
		pr_info("%s failed\n", __func__);

	return ret;
}
Ejemplo n.º 6
0
static void cpcap_adb_led_set(struct led_classdev *led_cdev,
			      enum led_brightness value)
{
	int cpcap_status = 0;

	struct cpcap_adb_led_data *cpcap_adb_led_data =
		container_of(led_cdev, struct cpcap_adb_led_data,
			     cpcap_adb_led_class_dev);

	if (debug)
		pr_info("%s %d\n", __func__, value);

	if (value > LED_OFF) {
		if ((cpcap_adb_led_data->regulator) &&
		    (cpcap_adb_led_data->regulator_state == 0)) {
			regulator_enable(cpcap_adb_led_data->regulator);
			cpcap_adb_led_data->regulator_state = 1;
		}

		cpcap_status = cpcap_regacc_write(cpcap_adb_led_data->cpcap,
					CPCAP_REG_ADLC,
					adb_led_config_data.on,
					CPCAP_ADB_ON_OFF_MASK);
	} else {
		if ((cpcap_adb_led_data->regulator) &&
		    (cpcap_adb_led_data->regulator_state == 1)) {
			regulator_disable(cpcap_adb_led_data->regulator);
			cpcap_adb_led_data->regulator_state = 0;
		}
		/* Due to a HW issue turn off the current then
		turn off the duty cycle */
		cpcap_status = cpcap_regacc_write(cpcap_adb_led_data->cpcap,
						  CPCAP_REG_ADLC,
						  CPCAP_ADB_OFF_1,
						  CPCAP_ADB_ON_OFF_MASK);

		cpcap_status = cpcap_regacc_write(cpcap_adb_led_data->cpcap,
						  CPCAP_REG_ADLC,
						  CPCAP_ADB_OFF_2,
						  CPCAP_ADB_ON_OFF_MASK);
	}

	if (cpcap_status < 0)
		pr_err("%s: Writing to the register failed for %i\n",
		       __func__, cpcap_status);

}
Ejemplo n.º 7
0
static int msg_ind_reg_write (struct cpcap_device *cpcap, unsigned reg,
    unsigned value, const char *func)
{
    int cpcap_status;
    cpcap_status = cpcap_regacc_write(cpcap, reg, value,
                  LD_MSG_IND_CPCAP_MASK);
    printk_cpcap("%s: cpcap_regacc_write(0x%x, 0x%x, 0x%x) = %d\n",
        func, reg, value, LD_MSG_IND_CPCAP_MASK, cpcap_status);
    return cpcap_status;
}
Ejemplo n.º 8
0
static int cpcap_regulator_set_mode(struct regulator_dev *rdev,
				    unsigned int mode)
{
	struct cpcap_device *cpcap = rdev_get_drvdata(rdev);
	int regltr_id;
	enum cpcap_reg regnr;
	int ret = 0;

	regltr_id = rdev_get_id(rdev);
	if (regltr_id != CPCAP_VAUDIO)
		return -EINVAL;

	regnr = cpcap_regltr_data[regltr_id].reg;

	if (mode == REGULATOR_MODE_NORMAL) {
		if (cpcap_regltr_data[regltr_id].mode_cntr == 0) {
			ret = cpcap_regacc_write(cpcap, regnr,
						 0,
						 CPCAP_BIT_AUDIO_LOW_PWR);
		}
		if (ret == 0)
			cpcap_regltr_data[regltr_id].mode_cntr++;
	} else if (mode == REGULATOR_MODE_STANDBY) {
		if (cpcap_regltr_data[regltr_id].mode_cntr == 1) {
			ret = cpcap_regacc_write(cpcap, regnr,
						 CPCAP_BIT_AUDIO_LOW_PWR,
						 CPCAP_BIT_AUDIO_LOW_PWR);
		} else if (WARN((cpcap_regltr_data[regltr_id].mode_cntr == 0),
				"Unbalanced modes for supply vaudio\n"))
			ret = -EIO;

		if (ret == 0)
			cpcap_regltr_data[regltr_id].mode_cntr--;
	}else if (mode == REGULATOR_MODE_IDLE ) {
             /*For case of  audio manager restart   set regulator to low power mode and reset counter */
			ret = cpcap_regacc_write(cpcap, regnr,
						 CPCAP_BIT_AUDIO_LOW_PWR,
						 CPCAP_BIT_AUDIO_LOW_PWR);
			cpcap_regltr_data[regltr_id].mode_cntr =0;
         }

	return ret;
}
Ejemplo n.º 9
0
static void cpcap_lm3554_power(struct cpcap_device *cpcap, int power_val)
{
	int gpio_state = 0;

	if (power_val != 0)
		gpio_state = CPCAP_BIT_GPIO0DRV;
	else
		gpio_state = 0;

	cpcap_regacc_write(cpcap,
			   CPCAP_REG_GPIO0, gpio_state, CPCAP_BIT_GPIO0DRV);
}
Ejemplo n.º 10
0
static int cpcap_regulator_disable(struct regulator_dev *rdev)
{
	struct cpcap_device *cpcap = rdev_get_drvdata(rdev);
	int regltr_id;
	enum cpcap_reg regnr;

	regltr_id = rdev_get_id(rdev);
	if (regltr_id >= CPCAP_NUM_REGULATORS)
		return -EINVAL;

	regnr = cpcap_regltr_data[regltr_id].reg;

	return cpcap_regacc_write(cpcap, regnr,
				  cpcap_regltr_data[regltr_id].off_mode_val,
				  cpcap_regltr_data[regltr_id].mode_mask);
}
Ejemplo n.º 11
0
static int cpcap_regulator_set_voltage(struct regulator_dev *rdev,
				       int min_uV, int max_uV, unsigned int *selector)
{
	struct cpcap_device *cpcap;
	int regltr_id;
	int retval;
	enum cpcap_reg regnr;
	int i;

	cpcap = rdev_get_drvdata(rdev);

	regltr_id = rdev_get_id(rdev);
	if (regltr_id >= CPCAP_NUM_REGULATORS)
		return -EINVAL;

	regnr = cpcap_regltr_data[regltr_id].reg;

	if (regltr_id == CPCAP_VRF1) {
		if (min_uV > 2500000)
			i = 0;
		else
			i = cpcap_regltr_data[regltr_id].volt_mask;
	} else {
		for (i = 0; i < cpcap_regltr_data[regltr_id].val_tbl_sz; i++)
			if (cpcap_regltr_data[regltr_id].val_tbl[i] >= min_uV)
				break;

		if (i >= cpcap_regltr_data[regltr_id].val_tbl_sz)
			i--;

		*selector = i;

		i <<= cpcap_regltr_data[regltr_id].volt_shft;

                i += cpcap_regltr_data[regltr_id].bit_offset_from_cpcap_lowest_voltage;
	}

	retval = cpcap_regacc_write(cpcap, regnr, i,
				    cpcap_regltr_data[regltr_id].volt_mask);

	if ((cpcap_regltr_data[regltr_id].volt_trans_time) && (retval == 0))
		udelay(cpcap_regltr_data[regltr_id].volt_trans_time);

	return retval;
}
Ejemplo n.º 12
0
void cpcap_irq_mask_all(struct cpcap_device *cpcap)
{
	int i;

	static const struct {
		unsigned short mask_reg;
		unsigned short valid;
	} int_reg[NUM_INT_REGS] = {
		{CPCAP_REG_INTM1, CPCAP_INT1_VALID_BITS},
		{CPCAP_REG_INTM2, CPCAP_INT2_VALID_BITS},
		{CPCAP_REG_INTM3, CPCAP_INT3_VALID_BITS},
		{CPCAP_REG_INTM4, CPCAP_INT4_VALID_BITS},
		{CPCAP_REG_MIM1,  CPCAP_INT5_VALID_BITS}
	};

	for (i = 0; i < NUM_INT_REGS; i++) {
		cpcap_regacc_write(cpcap, int_reg[i].mask_reg,
				   int_reg[i].valid,
				   int_reg[i].valid);
	}
}
Ejemplo n.º 13
0
static int cpcap_lm3559_probe(struct platform_device *pdev)
{
	int ret;
	struct lm3559_cpcap_data *info;

	pr_info("%s:CPCAP Probe enter\n", __func__);
	if (pdev == NULL) {
		pr_err("%s: platform data required\n", __func__);
		return -ENODEV;

	}

	info = kzalloc(sizeof(struct lm3559_cpcap_data), GFP_KERNEL);
	if (info == NULL) {
		ret = -ENOMEM;
		return ret;
	}

	info->cpcap_dev = pdev->dev.platform_data;
	platform_set_drvdata(pdev, info);

	ret = cpcap_regacc_write(info->cpcap_dev,
				 CPCAP_REG_GPIO0, CPCAP_BIT_GPIO0DIR,
				 CPCAP_BIT_GPIO0DIR);
	if (ret < 0) {
		pr_err("%s: cpcap reg write failed\n", __func__);
		kfree(info);
		return ret;
	}

	/* Toggle only when the device is present */
	cpcap_lm3559_power(info->cpcap_dev, 0);
	mdelay(5);
	cpcap_lm3559_power(info->cpcap_dev, 1);

	ret = i2c_add_driver(&lm3559_i2c_driver);

	pr_info("%s:CPCAP torch probe exit\n", __func__);
	return ret;
}
Ejemplo n.º 14
0
void force_to_detect_usb(void)
{
	unsigned char sense = 0;
	unsigned short value;
	cpcap_regacc_read(temp_data->cpcap, CPCAP_REG_INTS2, &value);
  
	/* Clear ASAP after read. */
	cpcap_regacc_write(temp_data->cpcap, CPCAP_REG_INT2,
			   (CPCAP_BIT_CHRGCURR1_I |
			    CPCAP_BIT_VBUSVLD_I |
			    CPCAP_BIT_SESSVLD_I |
			    CPCAP_BIT_SE1_I),
			   (CPCAP_BIT_CHRGCURR1_I |
			    CPCAP_BIT_VBUSVLD_I |
			    CPCAP_BIT_SESSVLD_I |
			    CPCAP_BIT_SE1_I));

	sense = ((value & CPCAP_BIT_VBUSVLD_S) ? 1 : 0);

	if (!sense)
		schedule_delayed_work(&temp_data->work, msecs_to_jiffies(0));
}
Ejemplo n.º 15
0
static void logged_cpcap_write(struct cpcap_device *cpcap, unsigned int reg,
			unsigned short int value, unsigned short int mask)
{
	if (mask != 0) {
		int ret_val = 0;
		pr_debug("%s: audio: reg %u, value 0x%x,mask 0x%x\n", __func__,
			CPCAP_REG_FOR_POWERIC_REG(reg), value, mask);
		ret_val = cpcap_regacc_write(cpcap, reg, value, mask);
		if (ret_val != 0)
			E("%s: w %04x m %04x -> r %u failed: %d\n", __func__,
				value, mask, reg, ret_val);
#if CPCAP_AUDIO_SPI_READBACK
		ret_val = cpcap_regacc_read(cpcap, reg, &value);
		if (ret_val == 0)
			pr_debug("%s: audio verify: reg %u: value 0x%x\n",
				__func__,
				CPCAP_REG_FOR_POWERIC_REG(reg), value);
		else
			E("%s: audio verify: reg %u FAILED\n", __func__,
				CPCAP_REG_FOR_POWERIC_REG(reg));
#endif
	}
}
Ejemplo n.º 16
0
static int __init cpcap_3mm5_probe(struct platform_device *pdev)
{
	int retval = 0;
	struct cpcap_3mm5_data *data;

	if (pdev->dev.platform_data == NULL) {
		dev_err(&pdev->dev, "no platform_data\n");
		return -EINVAL;
	}

	data = kzalloc(sizeof(*data), GFP_KERNEL);
	if (!data)
		return -ENOMEM;

	data->cpcap = pdev->dev.platform_data;
	data->audio_low_pwr_det = 1;
	data->audio_low_pwr_mac13 = 1;
	data->sdev.name = "h2w";
	data->sdev.print_name = print_name;
	switch_dev_register(&data->sdev);
	INIT_DELAYED_WORK(&data->work, mac13_work);
	platform_set_drvdata(pdev, data);

	data->regulator = regulator_get(NULL, "vaudio");
	if (IS_ERR(data->regulator)) {
		dev_err(&pdev->dev, "Could not get regulator for cpcap_3mm5\n");
		retval = PTR_ERR(data->regulator);
		goto free_mem;
	}

	regulator_set_voltage(data->regulator, 2775000, 2775000);

	/* configure GPIO2=high and GPIO4=low. */
	cpcap_regacc_write(data->cpcap, CPCAP_REG_GPIO2, 0, CPCAP_BIT_GPIO2DRV);
	cpcap_regacc_write(data->cpcap, CPCAP_REG_GPIO4, 0, CPCAP_BIT_GPIO4DRV);

	retval  = cpcap_irq_clear(data->cpcap, CPCAP_IRQ_HS);
	retval |= cpcap_irq_clear(data->cpcap, CPCAP_IRQ_MB2);
	retval |= cpcap_irq_clear(data->cpcap, CPCAP_IRQ_UC_PRIMACRO_5);
	retval |= cpcap_irq_clear(data->cpcap, CPCAP_IRQ_UC_PRIMACRO_13);
	if (retval)
		goto reg_put;

	retval = cpcap_irq_register(data->cpcap, CPCAP_IRQ_HS, hs_handler,
				    data);
	if (retval)
		goto reg_put;

	retval = cpcap_irq_register(data->cpcap, CPCAP_IRQ_MB2, key_handler,
				    data);
	if (retval)
		goto free_hs;

	retval = cpcap_irq_register(data->cpcap, CPCAP_IRQ_UC_PRIMACRO_5,
				    key_handler, data);
	if (retval)
		goto free_mb2;

	if (data->cpcap->vendor == CPCAP_VENDOR_ST) {
		retval = cpcap_irq_register(data->cpcap,
					    CPCAP_IRQ_UC_PRIMACRO_13,
					    mac13_handler, data);
		if (retval)
			goto free_mac5;

		cpcap_uc_start(data->cpcap, CPCAP_MACRO_13);
	}

	hs_handler(CPCAP_IRQ_HS, data);

	return 0;

free_mac5:
	cpcap_irq_free(data->cpcap, CPCAP_IRQ_UC_PRIMACRO_5);
free_mb2:
	cpcap_irq_free(data->cpcap, CPCAP_IRQ_MB2);
free_hs:
	cpcap_irq_free(data->cpcap, CPCAP_IRQ_HS);
reg_put:
	regulator_put(data->regulator);
free_mem:
	kfree(data);

	return retval;
}
Ejemplo n.º 17
0
static void detection_work(struct work_struct *work)
{
	struct cpcap_usb_det_data *data =
		container_of(work, struct cpcap_usb_det_data, work.work);
#ifdef CONFIG_TTA_CHARGER  
	static unsigned char first_time = 0;
#endif

	switch (data->state) {
	case CONFIG:
		vusb_enable(data);
		cpcap_irq_mask(data->cpcap, CPCAP_IRQ_CHRG_DET);
		cpcap_irq_mask(data->cpcap, CPCAP_IRQ_CHRG_CURR1);
		cpcap_irq_mask(data->cpcap, CPCAP_IRQ_SE1);
		cpcap_irq_mask(data->cpcap, CPCAP_IRQ_IDGND);
		cpcap_irq_mask(data->cpcap, CPCAP_IRQ_VBUSVLD);
#ifdef CONFIG_TTA_CHARGER
		cpcap_irq_mask(data->cpcap, CPCAP_IRQ_DMI);
#endif 
		configure_hardware(data, CPCAP_ACCY_UNKNOWN);

		data->state = SAMPLE_1;
		schedule_delayed_work(&data->work, msecs_to_jiffies(11));
		break;

	case SAMPLE_1:
		get_sense(data);
#ifdef CONFIG_TTA_CHARGER
		if (!(data->sense_tta.gpio_val) &&
			(data->sense & CPCAP_BIT_SESSVLD_S)) {
			disable_tta();
			enable_tta();
		}
#endif    
		data->state = SAMPLE_2;
		schedule_delayed_work(&data->work, msecs_to_jiffies(100));
		break;

	case SAMPLE_2:
		data->prev_sense = data->sense;
		get_sense(data);

		if (data->prev_sense != data->sense) {
			/* Stay in this state */
			data->state = SAMPLE_2;
			schedule_delayed_work(&data->work,
					      msecs_to_jiffies(100));
		} else if (!(data->sense & CPCAP_BIT_SE1_S) &&
			   (data->sense & CPCAP_BIT_ID_FLOAT_S) &&
			   !(data->sense & CPCAP_BIT_ID_GROUND_S) &&
			   !(data->sense & CPCAP_BIT_SESSVLD_S)) {
			data->state = IDENTIFY;
#ifdef CONFIG_TTA_CHARGER
			if (!(data->sense_tta.gpio_val))
				data->state = IDENTIFY_TTA;
#endif
			schedule_delayed_work(&data->work,
					      msecs_to_jiffies(100));
		} else {
			data->state = IDENTIFY;
#ifdef CONFIG_TTA_CHARGER
			if (!(data->sense & CPCAP_BIT_SESSVLD_S) &&
				!(data->sense_tta.gpio_val)) {
				data->state = IDENTIFY_TTA;
		}
#endif
			schedule_delayed_work(&data->work, 0);
		}
		break;
#ifdef CONFIG_TTA_CHARGER
	case IDENTIFY_TTA:
		configure_hardware(data, CPCAP_ACCY_TTA_CHARGER);
		data->state = IDENTIFY;
		schedule_delayed_work(&data->work, 0);
		break;
#endif
	case IDENTIFY:
		get_sense(data);
		data->state = CONFIG;

#ifdef CONFIG_TTA_CHARGER
		if ((data->sense_tta.dplus == data->sense_tta.dminus) &&
			!(data->sense_tta.gpio_val) &&
			!(data->sense & CPCAP_BIT_SESSVLD_S)) {
			notify_accy(data, CPCAP_ACCY_TTA_CHARGER);
			cpcap_irq_clear(data->cpcap, CPCAP_IRQ_DMI);
			cpcap_irq_unmask(data->cpcap, CPCAP_IRQ_DMI);
			data->state = TTA;
			disable_musb_int();

		} else if ((data->sense == SENSE_USB) ||
			(data->sense == SENSE_USB_FLASH)) {
			notify_accy(data, CPCAP_ACCY_USB);

			cpcap_irq_unmask(data->cpcap, CPCAP_IRQ_CHRG_DET);
			cpcap_irq_unmask(data->cpcap, CPCAP_IRQ_CHRG_CURR1);
			cpcap_irq_unmask(data->cpcap, CPCAP_IRQ_SE1);
			cpcap_irq_unmask(data->cpcap, CPCAP_IRQ_IDGND);

			/* Special handling of USB cable undetect. */
			data->state = USB;
		}
#else
		if ((data->sense == SENSE_USB) ||
		    (data->sense == SENSE_USB_FLASH)) {
			notify_accy(data, CPCAP_ACCY_USB);

			cpcap_irq_unmask(data->cpcap, CPCAP_IRQ_CHRG_DET);
			cpcap_irq_unmask(data->cpcap, CPCAP_IRQ_CHRG_CURR1);
			cpcap_irq_unmask(data->cpcap, CPCAP_IRQ_SE1);
			cpcap_irq_unmask(data->cpcap, CPCAP_IRQ_IDGND);

			/* Special handling of USB cable undetect. */
			data->state = USB;
		}
#endif
		else if (data->sense == SENSE_FACTORY) {
			notify_accy(data, CPCAP_ACCY_FACTORY);

			cpcap_irq_unmask(data->cpcap, CPCAP_IRQ_SE1);
#ifdef CONFIG_TTA_CHARGER
			disable_tta();
#endif
			/* Special handling of factory cable undetect. */
			data->state = FACTORY;
		} else if ((data->sense == SENSE_CHARGER_FLOAT) ||
			   (data->sense == SENSE_CHARGER)) {
			notify_accy(data, CPCAP_ACCY_CHARGER);

			cpcap_irq_unmask(data->cpcap, CPCAP_IRQ_CHRG_CURR1);
			cpcap_irq_unmask(data->cpcap, CPCAP_IRQ_SE1);
			cpcap_irq_unmask(data->cpcap, CPCAP_IRQ_IDGND);

			/* Special handling of charger undetect. */
			data->state = CHARGER;
		} else {
			notify_accy(data, CPCAP_ACCY_NONE);

			cpcap_irq_unmask(data->cpcap, CPCAP_IRQ_CHRG_DET);
			cpcap_irq_unmask(data->cpcap, CPCAP_IRQ_CHRG_CURR1);

			/* When a charger is unpowered by unplugging from the
			 * wall, VBUS voltage will drop below CHRG_DET (3.5V)
			 * until the ICHRG bits are cleared.  Once ICHRG is
			 * cleared, VBUS will rise above CHRG_DET, but below
			 * VBUSVLD (4.4V) briefly as it decays.  If the charger
			 * is re-powered while VBUS is within this window, the
			 * VBUSVLD interrupt is needed to trigger charger
			 * detection.
			 *
			 * VBUSVLD must be masked before going into suspend.
			 * See cpcap_usb_det_suspend() for details.
			 */
			cpcap_irq_unmask(data->cpcap, CPCAP_IRQ_VBUSVLD);
#ifdef CONFIG_TTA_CHARGER      
			disable_tta();
			enable_tta();
#endif      
		}
		break;
#ifdef CONFIG_TTA_CHARGER
	case TTA:
		get_sense(data);

		if ((data->sense_tta.dplus != data->sense_tta.dminus) ||
			(data->sense_tta.gpio_val)) {
			cpcap_irq_mask(data->cpcap, CPCAP_IRQ_DMI);
			disable_tta();
			enable_tta();
			data->state = CONFIG;
			enable_musb_int();
			schedule_delayed_work(&data->work, 0);
		} else {
			data->state = TTA;
			cpcap_irq_unmask(data->cpcap, CPCAP_IRQ_DMI);
		}
		break;
#endif
	case USB:
		get_sense(data);

		if ((data->sense & CPCAP_BIT_SE1_S) ||
		    (data->sense & CPCAP_BIT_ID_GROUND_S) ||
		    (!(data->sense & CPCAP_BIT_VBUSVLD_S))) {
			if (data->sense & CPCAP_BIT_SE1_S) {
				/* A partially inserted charger is now fully
				 * seated in the jack. Give SPI control of
				 * PullUp/down bits so SE1 can not be lost. */
				cpcap_regacc_write(data->cpcap, CPCAP_REG_USBC3,
						   CPCAP_BIT_PU_SPI |
						   CPCAP_BIT_DMPD_SPI |
						   CPCAP_BIT_DPPD_SPI,
						   CPCAP_BIT_PU_SPI |
						   CPCAP_BIT_DMPD_SPI |
						   CPCAP_BIT_DPPD_SPI);
			}

			data->state = CONFIG;
			schedule_delayed_work(&data->work, 0);
		} else {
			data->state = USB;

			cpcap_irq_unmask(data->cpcap, CPCAP_IRQ_CHRG_DET);
			cpcap_irq_unmask(data->cpcap, CPCAP_IRQ_CHRG_CURR1);
			cpcap_irq_unmask(data->cpcap, CPCAP_IRQ_SE1);
			cpcap_irq_unmask(data->cpcap, CPCAP_IRQ_IDGND);
		}
		break;

	case FACTORY:
		get_sense(data);

		/* The removal of a factory cable can only be detected if a
		 * charger is attached.
		 */
		if (data->sense & CPCAP_BIT_SE1_S) {
#ifdef CONFIG_TTA_CHARGER
			enable_tta();
#endif
			data->state = CONFIG;
			schedule_delayed_work(&data->work, 0);
		} else {
			data->state = FACTORY;
			cpcap_irq_unmask(data->cpcap, CPCAP_IRQ_SE1);
		}
		break;

	case CHARGER:
		get_sense(data);

		/* If the battery voltage is above the set charge voltage in
		 * CPCAP and ICHRG is set, CHRGCURR1 will be 0.  Do not undetect
		 * charger in this case. */
		if (!(data->sense & CPCAP_BIT_SE1_S) ||
		    (!(data->sense & CPCAP_BIT_VBUSVLD_S) &&
		     !(data->sense & CPCAP_BIT_CHRGCURR1_S))) {
			data->state = CONFIG;
			schedule_delayed_work(&data->work, 0);
		} else {
			data->state = CHARGER;

			cpcap_irq_unmask(data->cpcap, CPCAP_IRQ_CHRG_CURR1);
			cpcap_irq_unmask(data->cpcap, CPCAP_IRQ_SE1);
			cpcap_irq_unmask(data->cpcap, CPCAP_IRQ_IDGND);
		}
		break;

	default:
		/* This shouldn't happen.  Need to reset state machine. */
		vusb_disable(data);
		data->state = CONFIG;
		schedule_delayed_work(&data->work, 0);
		break;
	}
#ifdef CONFIG_TTA_CHARGER
	temp_data = data;
	if (!first_time) {
		enable_musb_int();
		first_time = 1;
	}
#endif
}
Ejemplo n.º 18
0
static int __init cpcap_usb_det_probe(struct platform_device *pdev)
{
	int retval;
	struct cpcap_usb_det_data *data;

	if (pdev->dev.platform_data == NULL) {
		dev_err(&pdev->dev, "no platform_data\n");
		return -EINVAL;
	}

	data = kzalloc(sizeof(*data), GFP_KERNEL);
	if (!data)
		return -ENOMEM;

	data->cpcap = pdev->dev.platform_data;
	data->state = CONFIG;
	platform_set_drvdata(pdev, data);
	INIT_DELAYED_WORK(&data->work, detection_work);
	data->usb_accy = CPCAP_ACCY_NONE;
	wake_lock_init(&data->wake_lock, WAKE_LOCK_SUSPEND, "usb");

	data->regulator = regulator_get(NULL, "vusb");
	if (IS_ERR(data->regulator)) {
		dev_err(&pdev->dev, "Could not get regulator for cpcap_usb\n");
		retval = PTR_ERR(data->regulator);
		goto free_mem;
	}
	regulator_set_voltage(data->regulator, 3300000, 3300000);

	retval = cpcap_irq_register(data->cpcap, CPCAP_IRQ_CHRG_DET,
				    int_handler, data);
	retval |= cpcap_irq_register(data->cpcap, CPCAP_IRQ_CHRG_CURR1,
				     int_handler, data);
	retval |= cpcap_irq_register(data->cpcap, CPCAP_IRQ_SE1,
				     int_handler, data);
	retval |= cpcap_irq_register(data->cpcap, CPCAP_IRQ_IDGND,
				     int_handler, data);
	retval |= cpcap_irq_register(data->cpcap, CPCAP_IRQ_VBUSVLD,
				     int_handler, data);
	retval |= cpcap_irq_register(data->cpcap, CPCAP_IRQ_DPI,
				     int_handler, data);
	retval |= cpcap_irq_register(data->cpcap, CPCAP_IRQ_DMI,
				     int_handler, data);
#ifdef CONFIG_TTA_CHARGER

	if (gpio_request(TTU_TTA_CHRG_DET_N_GPIO, "tta_chrg_cntr") < 0)
		return -EBUSY;

	set_irq_type(OMAP_GPIO_IRQ(TTU_TTA_CHRG_DET_N_GPIO),
			IRQ_TYPE_EDGE_FALLING);
	retval |= request_irq(
			OMAP_GPIO_IRQ(TTU_TTA_CHRG_DET_N_GPIO),
			(void *)isr_handler,
			IRQF_DISABLED, TTA_IRQ_NAME,
			data);
#endif
	/* Now that HW initialization is done, give USB control via ULPI. */
	retval |= cpcap_regacc_write(data->cpcap, CPCAP_REG_USBC3,
				     0, CPCAP_BIT_ULPI_SPI_SEL);

	if (retval != 0) {
		dev_err(&pdev->dev, "Initialization Error\n");
		retval = -ENODEV;
		goto free_irqs;
	}

	dev_info(&pdev->dev, "CPCAP USB detection device probed\n");

	/* Perform initial detection */
	detection_work(&(data->work.work));

	return 0;

free_irqs:
	cpcap_irq_free(data->cpcap, CPCAP_IRQ_VBUSVLD);
	cpcap_irq_free(data->cpcap, CPCAP_IRQ_IDGND);
	cpcap_irq_free(data->cpcap, CPCAP_IRQ_SE1);
	cpcap_irq_free(data->cpcap, CPCAP_IRQ_CHRG_CURR1);
	cpcap_irq_free(data->cpcap, CPCAP_IRQ_CHRG_DET);
	cpcap_irq_free(data->cpcap, CPCAP_IRQ_DPI);
	cpcap_irq_free(data->cpcap, CPCAP_IRQ_DMI);
#ifdef CONFIG_TTA_CHARGER
	free_irq(OMAP_GPIO_IRQ(TTU_TTA_CHRG_DET_N_GPIO), 0);
	gpio_free(TTU_TTA_CHRG_DET_N_GPIO);
#endif
	regulator_put(data->regulator);
free_mem:
	wake_lock_destroy(&data->wake_lock);
	kfree(data);

	return retval;
}
Ejemplo n.º 19
0
static int configure_hardware(struct cpcap_usb_det_data *data,
			      enum cpcap_accy accy)
{
	int retval;

	/* Take control of pull up from ULPI. */
	retval  = cpcap_regacc_write(data->cpcap, CPCAP_REG_USBC3,
				     CPCAP_BIT_PU_SPI,
				     CPCAP_BIT_PU_SPI);
	retval |= cpcap_regacc_write(data->cpcap, CPCAP_REG_USBC1,
				    CPCAP_BIT_DP150KPU,
				    (CPCAP_BIT_DP150KPU | CPCAP_BIT_DP1K5PU |
				     CPCAP_BIT_DM1K5PU | CPCAP_BIT_DPPD |
				     CPCAP_BIT_DMPD));
#ifdef CONFIG_TTA_CHARGER
	get_sense(data);
	if (!(data->sense_tta.dplus)) {
		retval |= cpcap_regacc_write(data->cpcap, CPCAP_REG_USBC3,
						    CPCAP_BIT_PU_SPI |
						    CPCAP_BIT_DMPD_SPI |
						    CPCAP_BIT_DPPD_SPI,
						    CPCAP_BIT_PU_SPI |
						    CPCAP_BIT_DMPD_SPI |
						    CPCAP_BIT_DPPD_SPI);

		retval |= cpcap_regacc_write(data->cpcap, CPCAP_REG_USBC1,
				CPCAP_BIT_DP150KPU,
				(CPCAP_BIT_DP150KPU | CPCAP_BIT_DP1K5PU |
				CPCAP_BIT_DM1K5PU | CPCAP_BIT_DPPD |
				CPCAP_BIT_DMPD));
	}
#endif

	switch (accy) {
	case CPCAP_ACCY_USB:
	case CPCAP_ACCY_FACTORY:
		retval |= cpcap_regacc_write(data->cpcap, CPCAP_REG_USBC1, 0,
					     CPCAP_BIT_VBUSPD);
		retval |= cpcap_regacc_write(data->cpcap, CPCAP_REG_USBC2,
					     CPCAP_BIT_USBXCVREN,
					     CPCAP_BIT_USBXCVREN);
		/* Give USB driver control of pull up via ULPI. */
		retval |= cpcap_regacc_write(data->cpcap, CPCAP_REG_USBC3,
					     0,
					     CPCAP_BIT_PU_SPI |
					     CPCAP_BIT_DMPD_SPI |
					     CPCAP_BIT_DPPD_SPI |
					     CPCAP_BIT_SUSPEND_SPI |
					     CPCAP_BIT_ULPI_SPI_SEL);

		if ((data->cpcap->vendor == CPCAP_VENDOR_ST) &&
			(data->cpcap->revision == CPCAP_REVISION_2_0))
				vusb_enable(data);

		break;

	case CPCAP_ACCY_CHARGER:
		retval |= cpcap_regacc_write(data->cpcap, CPCAP_REG_USBC1,
					     CPCAP_BIT_VBUSPD,
					     CPCAP_BIT_VBUSPD);
		break;

#ifdef CONFIG_TTA_CHARGER
	case CPCAP_ACCY_TTA_CHARGER:
		retval |= cpcap_regacc_write(data->cpcap, CPCAP_REG_USBC3,
						   CPCAP_BIT_PU_SPI |
						   CPCAP_BIT_DMPD_SPI |
						   CPCAP_BIT_DPPD_SPI,
						   CPCAP_BIT_PU_SPI |
						   CPCAP_BIT_DMPD_SPI |
						   CPCAP_BIT_DPPD_SPI);

		retval |= cpcap_regacc_write(data->cpcap, CPCAP_REG_USBC2,
					     CPCAP_BIT_USBXCVREN,
					     CPCAP_BIT_USBXCVREN);
    break;
#endif

	case CPCAP_ACCY_UNKNOWN:
		retval |= cpcap_regacc_write(data->cpcap, CPCAP_REG_USBC1, 0,
					     CPCAP_BIT_VBUSPD);
		break;

	case CPCAP_ACCY_NONE:
	default:
#ifdef CONFIG_TTA_CHARGER
		retval |= cpcap_regacc_write(data->cpcap,
					CPCAP_REG_USBC3,
					CPCAP_BIT_PU_SPI,
					CPCAP_BIT_PU_SPI |
					CPCAP_BIT_DMPD_SPI |
					CPCAP_BIT_DPPD_SPI);
#endif
		retval |= cpcap_regacc_write(data->cpcap, CPCAP_REG_USBC1,
					     CPCAP_BIT_VBUSPD,
					     CPCAP_BIT_VBUSPD);
		retval |= cpcap_regacc_write(data->cpcap, CPCAP_REG_USBC2, 0,
					     CPCAP_BIT_USBXCVREN);
		retval |= cpcap_regacc_write(data->cpcap, CPCAP_REG_USBC3,
					     CPCAP_BIT_DMPD_SPI |
					     CPCAP_BIT_DPPD_SPI |
					     CPCAP_BIT_SUSPEND_SPI |
					     CPCAP_BIT_ULPI_SPI_SEL,
					     CPCAP_BIT_DMPD_SPI |
					     CPCAP_BIT_DPPD_SPI |
					     CPCAP_BIT_SUSPEND_SPI |
					     CPCAP_BIT_ULPI_SPI_SEL);
		break;
	}

	if (retval != 0)
		retval = -EFAULT;

	return retval;
}
Ejemplo n.º 20
0
static int get_sense(struct cpcap_usb_det_data *data)
{
	int retval = -EFAULT;
	unsigned short value;
	struct cpcap_device *cpcap;

	if (!data)
		return -EFAULT;
	cpcap = data->cpcap;

	retval = cpcap_regacc_read(cpcap, CPCAP_REG_INTS1, &value);
	if (retval)
		return retval;

	/* Clear ASAP after read. */
	retval = cpcap_regacc_write(cpcap, CPCAP_REG_INT1,
				     (CPCAP_BIT_CHRG_DET_I |
				      CPCAP_BIT_ID_GROUND_I),
				     (CPCAP_BIT_CHRG_DET_I |
				      CPCAP_BIT_ID_GROUND_I));
	if (retval)
		return retval;

	data->sense = value & (CPCAP_BIT_ID_FLOAT_S |
			       CPCAP_BIT_ID_GROUND_S);

	retval = cpcap_regacc_read(cpcap, CPCAP_REG_INTS2, &value);
	if (retval)
		return retval;

	/* Clear ASAP after read. */
	retval = cpcap_regacc_write(cpcap, CPCAP_REG_INT2,
				    (CPCAP_BIT_CHRGCURR1_I |
				     CPCAP_BIT_VBUSVLD_I |
				     CPCAP_BIT_SESSVLD_I |
				     CPCAP_BIT_SE1_I),
				    (CPCAP_BIT_CHRGCURR1_I |
				     CPCAP_BIT_VBUSVLD_I |
				     CPCAP_BIT_SESSVLD_I |
				     CPCAP_BIT_SE1_I));
	if (retval)
		return retval;

	data->sense |= value & (CPCAP_BIT_CHRGCURR1_S |
				CPCAP_BIT_VBUSVLD_S |
				CPCAP_BIT_SESSVLD_S |
				CPCAP_BIT_SE1_S);

	retval = cpcap_regacc_read(cpcap, CPCAP_REG_INTS4, &value);
	if (retval)
		return retval;

	/* Clear ASAP after read. */
	retval = cpcap_regacc_write(cpcap, CPCAP_REG_INT4,
				     (CPCAP_BIT_DP_I |
				      CPCAP_BIT_DM_I),
				     (CPCAP_BIT_DP_I |
				      CPCAP_BIT_DM_I));
	if (retval)
		return retval;

	data->sense |= (value & (CPCAP_BIT_DP_S |
			       CPCAP_BIT_DM_S)) << CPCAP_SENSE4_LS;

#ifdef CONFIG_TTA_CHARGER
	data->sense_tta.dplus = ((value & CPCAP_BIT_DP_S) ? 1 : 0);
	data->sense_tta.dminus = ((value & CPCAP_BIT_DM_S) ? 1 : 0);
	data->sense_tta.gpio_val = gpio_get_value(TTU_TTA_CHRG_DET_N_GPIO);
#endif
	return 0;
}
Ejemplo n.º 21
0
static int cpcap_adb_led_probe(struct platform_device *pdev)
{
	int ret = 0;
	int cpcap_status = 0;
	struct cpcap_adb_led_data *info;

	if (pdev == NULL) {
		pr_err("%s: Platform device required\n", __func__);
		ret = -ENODEV;
		goto err_pd_or_kzalloc_failed;
	}
	info = kzalloc(sizeof(struct cpcap_adb_led_data), GFP_KERNEL);
	if (info == NULL) {
		ret = -ENOMEM;
		goto err_pd_or_kzalloc_failed;
	}

	if (pdev->dev.platform_data == NULL) {
		pr_err("%s: Platforn data required\n", __func__);
		ret = -ENODEV;
		goto err_pd_or_kzalloc_failed;
	}
	memcpy(&adb_led_config_data, pdev->dev.platform_data,
		sizeof(adb_led_config_data));

	info->cpcap = platform_get_drvdata(pdev);
	if (info->cpcap == NULL) {
		pr_err("%s: Driver data required\n", __func__);
		ret = -ENODEV;
		goto err_request_reg_failed;
	}
	platform_set_drvdata(pdev, info);

	info->regulator = regulator_get(NULL, CPCAP_ADB_LED_REG);
	if (IS_ERR(info->regulator)) {
		pr_err("%s: Cannot get %s regulator\n", __func__,
		       CPCAP_ADB_LED_REG);
		ret = PTR_ERR(info->regulator);
		goto err_request_reg_failed;

	}

	info->regulator_state = 0;

	cpcap_status = cpcap_regacc_write(info->cpcap,
					  CPCAP_REG_ADLC,
					  adb_led_config_data.init,
					  CPCAP_ADB_INIT_MASK);

	if (cpcap_status < 0)
		pr_err("%s: Writing to the register failed for %i\n",
		       __func__, cpcap_status);

	cpcap_status = cpcap_regacc_write(info->cpcap,
		CPCAP_REG_ABC,
		adb_led_config_data.abmode_config->abmode_init,
		CPCAP_ABMODE_INIT_MASK);

	if (cpcap_status < 0)
		pr_err("%s: Writing to the register failed for %i\n",
		       __func__, cpcap_status);

	info->cpcap_adb_led_class_dev.name = adb_led_config_data.class_name;
	info->cpcap_adb_led_class_dev.brightness_set = cpcap_adb_led_set;
	ret = led_classdev_register(&pdev->dev, &info->cpcap_adb_led_class_dev);
	if (ret < 0) {
		pr_err("%s:Register button backlight class failed\n", __func__);
		goto err_reg_button_class_failed;
	}

	if (debug)
		pr_info("%s successful\n", __func__);

	return ret;

err_reg_button_class_failed:
	if (info->regulator)
		regulator_put(info->regulator);
err_request_reg_failed:
	kfree(info);

err_pd_or_kzalloc_failed:
	if (debug)
		pr_info("%s failed\n", __func__);

	return ret;
}
Ejemplo n.º 22
0
#ifdef CONFIG_LEDS_AF_LED
	&cpcap_af_led,
#endif
};

static struct cpcap_device *misc_cpcap;

static int cpcap_reboot(struct notifier_block *this, unsigned long code,
			void *cmd)
{
	int ret = -1;
	int result = NOTIFY_DONE;
	char *mode = cmd;

	/* Disable the USB transceiver */
	ret = cpcap_regacc_write(misc_cpcap, CPCAP_REG_USBC2, 0,
				 CPCAP_BIT_USBXCVREN);

	if (ret) {
		dev_err(&(misc_cpcap->spi->dev),
			"Disable Transciever failure.\n");
		result = NOTIFY_BAD;
	}

	if (code == SYS_RESTART) {
		/* Set the soft reset bit in the cpcap */
		cpcap_regacc_write(misc_cpcap, CPCAP_REG_VAL1,
			CPCAP_BIT_SOFT_RESET,
			CPCAP_BIT_SOFT_RESET);
		if (mode != NULL && !strncmp("outofcharge", mode, 12)) {
			/* Set the outofcharge bit in the cpcap */
			ret = cpcap_regacc_write(misc_cpcap, CPCAP_REG_VAL1,
Ejemplo n.º 23
0
static void hs_handler(enum cpcap_irqs irq, void *data)
{
	struct cpcap_3mm5_data *data_3mm5 = data;
	int new_state = NO_DEVICE;

	if (irq != CPCAP_IRQ_HS)
		return;

	/* HS sense of 1 means no headset present, 0 means headset attached. */
	if (cpcap_irq_sense(data_3mm5->cpcap, CPCAP_IRQ_HS, 1) == 1) {
		cpcap_regacc_write(data_3mm5->cpcap, CPCAP_REG_TXI, 0,
				   (CPCAP_BIT_MB_ON2 | CPCAP_BIT_PTT_CMP_EN));
		cpcap_regacc_write(data_3mm5->cpcap, CPCAP_REG_RXOA, 0,
				   CPCAP_BIT_ST_HS_CP_EN);
		audio_low_power_set(data_3mm5, &data_3mm5->audio_low_pwr_det);

		cpcap_irq_mask(data_3mm5->cpcap, CPCAP_IRQ_MB2);
		cpcap_irq_mask(data_3mm5->cpcap, CPCAP_IRQ_UC_PRIMACRO_5);

		cpcap_irq_clear(data_3mm5->cpcap, CPCAP_IRQ_MB2);
		cpcap_irq_clear(data_3mm5->cpcap, CPCAP_IRQ_UC_PRIMACRO_5);

		cpcap_irq_unmask(data_3mm5->cpcap, CPCAP_IRQ_HS);

		send_key_event(data_3mm5, 0);

		/* Config mux switch to accy detection. */
		cpcap_regacc_write(data_3mm5->cpcap, CPCAP_REG_GPIO2, 0,
				CPCAP_BIT_GPIO2DRV);
		cpcap_regacc_write(data_3mm5->cpcap, CPCAP_REG_GPIO4, 0,
				CPCAP_BIT_GPIO4DRV);
		cpcap_uc_stop(data_3mm5->cpcap, CPCAP_MACRO_5);
	} else {
		/* Config mux switch to pass headset mic. */
		cpcap_regacc_write(data_3mm5->cpcap, CPCAP_REG_GPIO2, 0,
					CPCAP_BIT_GPIO2DRV);
		cpcap_regacc_write(data_3mm5->cpcap, CPCAP_REG_GPIO4,
					CPCAP_BIT_GPIO4DRV, CPCAP_BIT_GPIO4DRV);

		cpcap_regacc_write(data_3mm5->cpcap, CPCAP_REG_TXI,
				   (CPCAP_BIT_MB_ON2 | CPCAP_BIT_PTT_CMP_EN),
				   (CPCAP_BIT_MB_ON2 | CPCAP_BIT_PTT_CMP_EN));
		cpcap_regacc_write(data_3mm5->cpcap, CPCAP_REG_RXOA,
				   CPCAP_BIT_ST_HS_CP_EN,
				   CPCAP_BIT_ST_HS_CP_EN);
		audio_low_power_clear(data_3mm5, &data_3mm5->audio_low_pwr_det);

		/* Give PTTS time to settle 10ms */
		msleep(11);

		if (cpcap_irq_sense(data_3mm5->cpcap, CPCAP_IRQ_PTT, 1) <= 0) {
			/* Headset without mic and MFB is detected. (May also
			 * be a headset with the MFB pressed.) */
			new_state = HEADSET_WITHOUT_MIC;
		} else {
			new_state = HEADSET_WITH_MIC;
			/* Config mux switch to pass headset mic. */
			cpcap_regacc_write(data_3mm5->cpcap, CPCAP_REG_GPIO2, 0,
					CPCAP_BIT_GPIO2DRV);
			cpcap_regacc_write(data_3mm5->cpcap, CPCAP_REG_GPIO4,
					CPCAP_BIT_GPIO4DRV, CPCAP_BIT_GPIO4DRV);
		}

		cpcap_irq_clear(data_3mm5->cpcap, CPCAP_IRQ_MB2);
		cpcap_irq_clear(data_3mm5->cpcap, CPCAP_IRQ_UC_PRIMACRO_5);

		cpcap_irq_unmask(data_3mm5->cpcap, CPCAP_IRQ_HS);
		cpcap_irq_unmask(data_3mm5->cpcap, CPCAP_IRQ_MB2);
		cpcap_irq_unmask(data_3mm5->cpcap, CPCAP_IRQ_UC_PRIMACRO_5);

		cpcap_uc_start(data_3mm5->cpcap, CPCAP_MACRO_5);
		headset_in_stamp = jiffies;
	}

	switch_set_state(&data_3mm5->sdev, new_state);
	if (data_3mm5->cpcap->h2w_new_state)
		data_3mm5->cpcap->h2w_new_state(new_state);

	dev_info(&data_3mm5->cpcap->spi->dev, "New headset state: %d\n",
		 new_state);
}
Ejemplo n.º 24
0
static void hs_handler(enum cpcap_irqs irq, void *data)
{
	struct cpcap_3mm5_data *data_3mm5 = data;
	int new_state = NO_DEVICE;

	if (irq != CPCAP_IRQ_HS)
		return;

	/* HS sense of 1 means no headset present, 0 means headset attached. */
	if (cpcap_irq_sense(data_3mm5->cpcap, CPCAP_IRQ_HS, 1) == 1) {
		cpcap_regacc_write(data_3mm5->cpcap, CPCAP_REG_TXI, 0,
				   (CPCAP_BIT_MB_ON2 | CPCAP_BIT_PTT_CMP_EN));
		cpcap_regacc_write(data_3mm5->cpcap, CPCAP_REG_RXOA, 0,
				   CPCAP_BIT_ST_HS_CP_EN);
		audio_low_power_set(data_3mm5, &data_3mm5->audio_low_pwr_det);

		cpcap_irq_mask(data_3mm5->cpcap, CPCAP_IRQ_MB2);
		cpcap_irq_mask(data_3mm5->cpcap, CPCAP_IRQ_UC_PRIMACRO_5);

		cpcap_irq_clear(data_3mm5->cpcap, CPCAP_IRQ_MB2);
		cpcap_irq_clear(data_3mm5->cpcap, CPCAP_IRQ_UC_PRIMACRO_5);

		cpcap_irq_unmask(data_3mm5->cpcap, CPCAP_IRQ_HS);

		send_key_event(data_3mm5, 0);

		data_3mm5->unsupported_headset=0;

		cpcap_uc_stop(data_3mm5->cpcap, CPCAP_BANK_PRIMARY, CPCAP_MACRO_5);
	} else {
		cpcap_regacc_write(data_3mm5->cpcap, CPCAP_REG_TXI,
				   (CPCAP_BIT_MB_ON2 | CPCAP_BIT_PTT_CMP_EN),
				   (CPCAP_BIT_MB_ON2 | CPCAP_BIT_PTT_CMP_EN));
		cpcap_regacc_write(data_3mm5->cpcap, CPCAP_REG_RXOA,
				   CPCAP_BIT_ST_HS_CP_EN,
				   CPCAP_BIT_ST_HS_CP_EN);
		audio_low_power_clear(data_3mm5, &data_3mm5->audio_low_pwr_det);

		/* Give PTTS time to settle */
		mdelay(2);

		if (cpcap_irq_sense(data_3mm5->cpcap, CPCAP_IRQ_PTT, 1) <= 0) {
			/* Headset without mic and MFB is detected. (May also
			 * be a headset with the MFB pressed.) */
			new_state = HEADSET_WITHOUT_MIC;
		} else {
		 if(cpcap_irq_sense(data_3mm5->cpcap, CPCAP_IRQ_MB2, 1) == 0) {
/*cvk011c: This is an Apple HS  and  its microphone will not work with CPCAP due to HW problem.
 Detect it as  HS without mic to avoid  problems with HS BTN detection and  MIC audio */
                		new_state = HEADSET_WITHOUT_MIC;
				dev_info(&data_3mm5->cpcap->spi->dev, "Unsupported headset detected\n");
				data_3mm5->unsupported_headset=1;
			}else
				new_state = HEADSET_WITH_MIC;
         	}

		cpcap_irq_clear(data_3mm5->cpcap, CPCAP_IRQ_MB2);
		cpcap_irq_clear(data_3mm5->cpcap, CPCAP_IRQ_UC_PRIMACRO_5);

		cpcap_irq_unmask(data_3mm5->cpcap, CPCAP_IRQ_HS);
		cpcap_irq_unmask(data_3mm5->cpcap, CPCAP_IRQ_MB2);
		cpcap_irq_unmask(data_3mm5->cpcap, CPCAP_IRQ_UC_PRIMACRO_5);

		cpcap_uc_start(data_3mm5->cpcap, CPCAP_BANK_PRIMARY, CPCAP_MACRO_5);
	}

	switch_set_state(&data_3mm5->sdev, new_state);
	if (data_3mm5->cpcap->h2w_new_state)
		data_3mm5->cpcap->h2w_new_state(new_state);

	dev_info(&data_3mm5->cpcap->spi->dev, "New headset state: %d\n",
		 new_state);
}