示例#1
0
void tegra_auto_hotplug_governor(unsigned int cpu_freq, bool suspend)
{
	unsigned long up_delay, top_freq, bottom_freq;

	if (!is_g_cluster_present())
		return;

	if (hp_state == TEGRA_HP_DISABLED)
		return;

	if (suspend) {
		hp_state = TEGRA_HP_IDLE;

		/* Switch to G-mode if suspend rate is high enough */
		if (is_lp_cluster() && (cpu_freq >= idle_bottom_freq)) {
			if (!clk_set_parent(cpu_clk, cpu_g_clk)) {
				hp_stats_update(CONFIG_NR_CPUS, false);
				hp_stats_update(0, true);
			}
		}
		return;
	}

	if (is_lp_cluster()) {
		up_delay = up2g0_delay;
		top_freq = idle_top_freq;
		bottom_freq = 0;
	} else {
		up_delay = up2gn_delay;
		top_freq = idle_bottom_freq;
		bottom_freq = idle_bottom_freq;
	}

	if (pm_qos_request(PM_QOS_MIN_ONLINE_CPUS) >= 2) {
		if (hp_state != TEGRA_HP_UP) {
			hp_state = TEGRA_HP_UP;
			queue_delayed_work(
				hotplug_wq, &hotplug_work, up_delay);
		}
		return;
	}

	switch (hp_state) {
	case TEGRA_HP_IDLE:
		if (cpu_freq > top_freq) {
			hp_state = TEGRA_HP_UP;
			queue_delayed_work(
				hotplug_wq, &hotplug_work, up_delay);
		} else if (cpu_freq <= bottom_freq) {
			hp_state = TEGRA_HP_DOWN;
			queue_delayed_work(
				hotplug_wq, &hotplug_work, down_delay);
		}
		break;
	case TEGRA_HP_DOWN:
		if (cpu_freq > top_freq) {
			hp_state = TEGRA_HP_UP;
			queue_delayed_work(
				hotplug_wq, &hotplug_work, up_delay);
		} else if (cpu_freq > bottom_freq) {
			hp_state = TEGRA_HP_IDLE;
		}
		break;
	case TEGRA_HP_UP:
		if (cpu_freq <= bottom_freq) {
			hp_state = TEGRA_HP_DOWN;
			queue_delayed_work(
				hotplug_wq, &hotplug_work, down_delay);
		} else if (cpu_freq <= top_freq) {
			hp_state = TEGRA_HP_IDLE;
		}
		break;
	default:
		pr_err("%s: invalid tegra hotplug state %d\n",
		       __func__, hp_state);
		BUG();
	}
}
static void panel_esd_start_check(struct mipi_dsi_data *dsi_data)
{
	queue_delayed_work(dsi_data->esd_wq, &dsi_data->esd_work,
			   PANEL_ESD_CHECK_PERIOD);
}
示例#3
0
extern void pm8058_drvx_led_brightness_set(struct led_classdev *led_cdev,
					   enum led_brightness brightness)
{
	struct pm8058_led_data *ldata;
	int *pduties;
	int id, mode;
	int lut_flag;
	int milliamps;
	int enable = 0;

	ldata = container_of(led_cdev, struct pm8058_led_data, ldev);

	pwm_disable(ldata->pwm_led);
	cancel_delayed_work_sync(&ldata->led_delayed_work);

	id = bank_to_id(ldata->bank);
	mode = (id == PM_PWM_LED_KPD) ? PM_PWM_CONF_PWM1 :
					PM_PWM_CONF_PWM1 + (ldata->bank - 4);

	brightness = (brightness > LED_FULL) ? LED_FULL : brightness;
	brightness = (brightness < LED_OFF) ? LED_OFF : brightness;
	LED_INFO_LOG("%s: bank %d brightness %d +\n", __func__,
	       ldata->bank, brightness);

	enable = (brightness) ? 1 : 0;
	if (strcmp(ldata->ldev.name, "charming-led") == 0)
		charming_led_enable(enable);

	lut_flag = ldata->lut_flag & ~(PM_PWM_LUT_LOOP | PM_PWM_LUT_REVERSE);

	if (brightness) {
		milliamps = (ldata->flags & PM8058_LED_DYNAMIC_BRIGHTNESS_EN) ?
			    ldata->out_current * brightness / LED_FULL :
			    ldata->out_current;

		printk(KERN_INFO "%s: flags %d current %d\n", __func__,
			ldata->flags, milliamps);

		pm8058_pwm_config_led(ldata->pwm_led, id, mode, milliamps);
		if (ldata->flags & PM8058_LED_LTU_EN) {
			pduties = &duties[ldata->start_index];
			pm8058_pwm_lut_config(ldata->pwm_led,
					      ldata->period_us,
					      pduties,
					      ldata->duty_time_ms,
					      ldata->start_index,
					      ldata->duites_size,
					      0, 0,
					      lut_flag);
			pm8058_pwm_lut_enable(ldata->pwm_led, 0);
			pm8058_pwm_lut_enable(ldata->pwm_led, 1);
		} else {
			pwm_config(ldata->pwm_led, 64000, 64000);
			pwm_enable(ldata->pwm_led);
		}
	} else {
		if (ldata->flags & PM8058_LED_LTU_EN) {
			wake_lock(&pmic_led_wake_lock);
			pduties = &duties[ldata->start_index +
					  ldata->duites_size];
			pm8058_pwm_lut_config(ldata->pwm_led,
					      ldata->period_us,
					      pduties,
					      ldata->duty_time_ms,
					      ldata->start_index +
					      ldata->duites_size,
					      ldata->duites_size,
					      0, 0,
					      lut_flag);
			pm8058_pwm_lut_enable(ldata->pwm_led, 1);
			queue_delayed_work(g_led_work_queue,
					   &ldata->led_delayed_work,
					   msecs_to_jiffies(ldata->duty_time_ms * ldata->duty_time_ms));

			LED_INFO_LOG("%s: bank %d fade out brightness %d -\n", __func__,
			ldata->bank, brightness);
			return;
		} else
			pwm_disable(ldata->pwm_led);
		pm8058_pwm_config_led(ldata->pwm_led, id, mode, 0);
	}
	LED_INFO_LOG("%s: bank %d brightness %d -\n", __func__, ldata->bank, brightness);
}
示例#4
0
static int rtl_op_config(struct ieee80211_hw *hw, u32 changed)
{
	struct rtl_priv *rtlpriv = rtl_priv(hw);
	struct rtl_phy *rtlphy = &(rtlpriv->phy);
	struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
	struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw));
	struct ieee80211_conf *conf = &hw->conf;

	if (mac->skip_scan)
		return 1;


	mutex_lock(&rtlpriv->locks.conf_mutex);
	if (changed & IEEE80211_CONF_CHANGE_LISTEN_INTERVAL) {	/* BIT(2) */
		RT_TRACE(COMP_MAC80211, DBG_LOUD,
			 ("IEEE80211_CONF_CHANGE_LISTEN_INTERVAL\n"));
	}

	/*For IPS */
	if (changed & IEEE80211_CONF_CHANGE_IDLE) {
		if (hw->conf.flags & IEEE80211_CONF_IDLE)
			rtl_ips_nic_off(hw);
		else
			rtl_ips_nic_on(hw);
	} else {
		/*
		 *although rfoff may not cause by ips, but we will
		 *check the reason in set_rf_power_state function
		 */
		if (unlikely(ppsc->rfpwr_state == ERFOFF))
			rtl_ips_nic_on(hw);
	}

	/*For LPS */
	if (changed & IEEE80211_CONF_CHANGE_PS) {
		cancel_delayed_work(&rtlpriv->works.ps_work);
		cancel_delayed_work(&rtlpriv->works.ps_rfon_wq);
		if (conf->flags & IEEE80211_CONF_PS) {
			rtlpriv->psc.sw_ps_enabled = true;
			/* sleep here is must, or we may recv the beacon and
			 * cause mac80211 into wrong ps state, this will cause
			 * power save nullfunc send fail, and further cause
			 * pkt loss, So sleep must quickly but not immediately
			 * because that will cause nullfunc send by mac80211
			 * fail, and cause pkt loss, we have tested that 5mA
			 * is worked very well */
			if (!rtlpriv->psc.multi_buffered)
				queue_delayed_work(rtlpriv->works.rtl_wq,
						   &rtlpriv->works.ps_work,
						   MSECS(5));
		} else {
			rtl_swlps_rf_awake(hw);
			rtlpriv->psc.sw_ps_enabled = false;
		}
	}

	if (changed & IEEE80211_CONF_CHANGE_RETRY_LIMITS) {
		RT_TRACE(COMP_MAC80211, DBG_LOUD,
			 ("IEEE80211_CONF_CHANGE_RETRY_LIMITS %x\n",
			  hw->conf.long_frame_max_tx_count));
		mac->retry_long = hw->conf.long_frame_max_tx_count;
		mac->retry_short = hw->conf.long_frame_max_tx_count;
		rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_RETRY_LIMIT,
				(u8 *) (&hw->conf.long_frame_max_tx_count));
	}

	if (changed & IEEE80211_CONF_CHANGE_CHANNEL) {
		struct ieee80211_channel *channel = hw->conf.chandef.chan;
		enum nl80211_channel_type channel_type =
				cfg80211_get_chandef_type(&(hw->conf.chandef));
		u8 wide_chan = (u8) channel->hw_value;

		if (mac->act_scanning)
			mac->n_channels++;

		if (rtlpriv->dm.supp_phymode_switch &&
			mac->link_state < MAC80211_LINKED &&
			!mac->act_scanning) {
			if (rtlpriv->cfg->ops->check_switch_to_dmdp)
				rtlpriv->cfg->ops->check_switch_to_dmdp(hw);
		}

		/*
		 *because we should back channel to
		 *current_network.chan in in scanning,
		 *So if set_chan == current_network.chan
		 *we should set it.
		 *because mac80211 tell us wrong bw40
		 *info for cisco1253 bw20, so we modify
		 *it here based on UPPER & LOWER
		 */
		switch (channel_type) {
			case NL80211_CHAN_HT20:
			case NL80211_CHAN_NO_HT:
				/* SC */
				mac->cur_40_prime_sc =
					PRIME_CHNL_OFFSET_DONT_CARE;
				rtlphy->current_chan_bw = HT_CHANNEL_WIDTH_20;
				mac->bw_40 = false;
				break;
			case NL80211_CHAN_HT40MINUS:
				/* SC */
				mac->cur_40_prime_sc = PRIME_CHNL_OFFSET_UPPER;
				rtlphy->current_chan_bw =
					HT_CHANNEL_WIDTH_20_40;
				mac->bw_40 = true;

				/*wide channel */
				wide_chan -= 2;

				break;
			case NL80211_CHAN_HT40PLUS:
				/* SC */
				mac->cur_40_prime_sc = PRIME_CHNL_OFFSET_LOWER;
				rtlphy->current_chan_bw =
					HT_CHANNEL_WIDTH_20_40;
				mac->bw_40 = true;

				/*wide channel */
				wide_chan += 2;

				break;
			default:
				mac->bw_40 = false;
				RT_TRACE(COMP_ERR, DBG_EMERG,
						("switch case not processed \n"));
				break;
		}

		if (wide_chan <= 0)
			wide_chan = 1;

		/* in scanning, when before we offchannel we may send a ps=1
		 * null to AP, and then we may send a ps = 0 null to AP quickly,
		 * but first null have cause AP's put lots of packet to hw tx
		 * buffer, these packet must be tx before off channel so we must
		 * delay more time to let AP flush these packets before
		 * offchannel, or dis-association or delete BA will happen by AP
		 */
		if (rtlpriv->mac80211.offchan_deley) {
			rtlpriv->mac80211.offchan_deley = false;
			mdelay(50);
		}

		rtlphy->current_channel = wide_chan;

		rtlpriv->cfg->ops->switch_channel(hw);
		rtlpriv->cfg->ops->set_channel_access(hw);
		rtlpriv->cfg->ops->set_bw_mode(hw,
			channel_type);
	}

	mutex_unlock(&rtlpriv->locks.conf_mutex);

	return 0;
}
示例#5
0
static void insert_headset(struct work_struct *work)
{
	struct delayed_work *dwork = container_of(work, struct delayed_work, work);
	struct hsd_info *hi = container_of(dwork, struct hsd_info, work_for_insert);

	int earjack_type;

	int value = gpio_get_value_cansleep(hi->gpio_detect);

	if(value != EARJACK_INSERTED) {
		HSD_ERR("insert_headset but actually Fake inserted state!!\n");
		return;
	}
	else {
#ifdef HEADSET_REMOVE_ERROR
		insert_state_check = 1;
#endif
//		mutex_lock(&hi->mutex_lock);
//		switch_set_state(&hi->sdev, LGE_HEADSET);
//		mutex_unlock(&hi->mutex_lock);
	}

	HSD_DBG("insert_headset");

	if (hi->set_headset_mic_bias)
		hi->set_headset_mic_bias(TRUE);

	gpio_set_value_cansleep(hi->gpio_mic_en, 1);

	msleep(hi->latency_for_detection); // 75 -> 10 ms

	earjack_type = gpio_get_value_cansleep(hi->gpio_jpole);

	if (earjack_type == EARJACK_TYPE_3_POLE) {
		HSD_DBG("3 polarity earjack");

		if (hi->set_headset_mic_bias)
			hi->set_headset_mic_bias(FALSE);

		atomic_set(&hi->is_3_pole_or_not, 1);

		mutex_lock(&hi->mutex_lock);
		switch_set_state(&hi->sdev, LGE_HEADSET_NO_MIC);
		mutex_unlock(&hi->mutex_lock);

		input_report_switch(hi->input, SW_HEADPHONE_INSERT, 1);
		input_sync(hi->input);
	} else {
		HSD_DBG("4 polarity earjack");

		atomic_set(&hi->is_3_pole_or_not, 0);

		cancel_delayed_work_sync(&(hi->work_for_key_det_enable));
		queue_delayed_work(local_fsa8008_workqueue, &(hi->work_for_key_det_enable), FSA8008_KEY_EN_DELAY_MS );


		mutex_lock(&hi->mutex_lock);
		switch_set_state(&hi->sdev, LGE_HEADSET);
		mutex_unlock(&hi->mutex_lock);

		input_report_switch(hi->input, SW_HEADPHONE_INSERT, 1);
		input_sync(hi->input); // 2012-07-01, [email protected] - to prevent a lost uevent of earjack inserted
		input_report_switch(hi->input, SW_MICROPHONE_INSERT, 1);
		input_sync(hi->input);
	}
#ifdef HEADSET_REMOVE_ERROR
	insert_state_check = 0;
#endif

}
示例#6
0
static void aliasguid_query_handler(int status,
				    struct ib_sa_guidinfo_rec *guid_rec,
				    void *context)
{
	struct mlx4_ib_dev *dev;
	struct mlx4_alias_guid_work_context *cb_ctx = context;
	u8 port_index ;
	int i;
	struct mlx4_sriov_alias_guid_info_rec_det *rec;
	unsigned long flags, flags1;

	if (!context)
		return;

	dev = cb_ctx->dev;
	port_index = cb_ctx->port - 1;
	rec = &dev->sriov.alias_guid.ports_guid[port_index].
		all_rec_per_port[cb_ctx->block_num];

	if (status) {
		rec->status = MLX4_GUID_INFO_STATUS_IDLE;
		pr_debug("(port: %d) failed: status = %d\n",
			 cb_ctx->port, status);
		goto out;
	}

	if (guid_rec->block_num != cb_ctx->block_num) {
		pr_err("block num mismatch: %d != %d\n",
		       cb_ctx->block_num, guid_rec->block_num);
		goto out;
	}

	pr_debug("lid/port: %d/%d, block_num: %d\n",
		 be16_to_cpu(guid_rec->lid), cb_ctx->port,
		 guid_rec->block_num);

	rec = &dev->sriov.alias_guid.ports_guid[port_index].
		all_rec_per_port[guid_rec->block_num];

	rec->status = MLX4_GUID_INFO_STATUS_SET;
	rec->method = MLX4_GUID_INFO_RECORD_SET;

	for (i = 0 ; i < NUM_ALIAS_GUID_IN_REC; i++) {
		__be64 tmp_cur_ag;
		tmp_cur_ag = *(__be64 *)&guid_rec->guid_info_list[i * GUID_REC_SIZE];
		/* check if the SM didn't assign one of the records.
		 * if it didn't, if it was not sysadmin request:
		 * ask the SM to give a new GUID, (instead of the driver request).
		 */
		if (tmp_cur_ag == MLX4_NOT_SET_GUID) {
			mlx4_ib_warn(&dev->ib_dev, "%s:Record num %d in "
				     "block_num: %d was declined by SM, "
				     "ownership by %d (0 = driver, 1=sysAdmin,"
				     " 2=None)\n", __func__, i,
				     guid_rec->block_num, rec->ownership);
			if (rec->ownership == MLX4_GUID_DRIVER_ASSIGN) {
				/* if it is driver assign, asks for new GUID from SM*/
				*(__be64 *)&rec->all_recs[i * GUID_REC_SIZE] =
					MLX4_NOT_SET_GUID;

				/* Mark the record as not assigned, and let it
				 * be sent again in the next work sched.*/
				rec->status = MLX4_GUID_INFO_STATUS_IDLE;
				rec->guid_indexes |= mlx4_ib_get_aguid_comp_mask_from_ix(i);
			}
		} else {
		       /* properly assigned record. */
		       /* We save the GUID we just got from the SM in the
			* admin_guid in order to be persistent, and in the
			* request from the sm the process will ask for the same GUID */
			if (rec->ownership == MLX4_GUID_SYSADMIN_ASSIGN &&
			    tmp_cur_ag != *(__be64 *)&rec->all_recs[i * GUID_REC_SIZE]) {
				/* the sysadmin assignment failed.*/
				mlx4_ib_warn(&dev->ib_dev, "%s: Failed to set"
					     " admin guid after SysAdmin "
					     "configuration. "
					     "Record num %d in block_num:%d "
					     "was declined by SM, "
					     "new val(0x%llx) was kept\n",
					      __func__, i,
					     guid_rec->block_num,
					     (long long)be64_to_cpu(*(__be64 *) &
							 rec->all_recs[i * GUID_REC_SIZE]));
			} else {
				memcpy(&rec->all_recs[i * GUID_REC_SIZE],
				       &guid_rec->guid_info_list[i * GUID_REC_SIZE],
				       GUID_REC_SIZE);
			}
		}
	}
	/*
	The func is call here to close the cases when the
	sm doesn't send smp, so in the sa response the driver
	notifies the slave.
	*/
	mlx4_ib_notify_slaves_on_guid_change(dev, guid_rec->block_num,
					     cb_ctx->port,
					     guid_rec->guid_info_list);
out:
	spin_lock_irqsave(&dev->sriov.going_down_lock, flags);
	spin_lock_irqsave(&dev->sriov.alias_guid.ag_work_lock, flags1);
	if (!dev->sriov.is_going_down)
		queue_delayed_work(dev->sriov.alias_guid.ports_guid[port_index].wq,
				   &dev->sriov.alias_guid.ports_guid[port_index].
				   alias_guid_work, 0);
	if (cb_ctx->sa_query) {
		list_del(&cb_ctx->list);
		kfree(cb_ctx);
	} else
		complete(&cb_ctx->done);
	spin_unlock_irqrestore(&dev->sriov.alias_guid.ag_work_lock, flags1);
	spin_unlock_irqrestore(&dev->sriov.going_down_lock, flags);
}
示例#7
0
static int p3_get_bat_level(struct power_supply *bat_ps)
{
	struct battery_data *battery = container_of(bat_ps,
				struct battery_data, psy_battery);
	int fg_soc;
	int fg_vfsoc;
	int fg_vcell;
	int fg_current;
	int avg_current;
	int recover_flag = 0;

	recover_flag = fg_check_cap_corruption();

	/* check VFcapacity every five minutes */
	if (!(battery->fg_chk_cnt++ % 10)) {
		fg_check_vf_fullcap_range();
		battery->fg_chk_cnt = 1;
	}

	fg_soc = get_fuelgauge_value(FG_LEVEL);
	if (fg_soc < 0) {
		pr_info("Can't read soc!!!");
		fg_soc = battery->info.level;
	}

	if (!check_jig_on() && !max17042_chip_data->info.low_batt_comp_flag) {
		if (((fg_soc+5) < max17042_chip_data->info.previous_repsoc) ||
			(fg_soc > (max17042_chip_data->info.previous_repsoc+5)))
			battery->fg_skip = 1;
	}

	/* skip one time (maximum 30 seconds) because of corruption. */
	if (battery->fg_skip) {
		pr_info("%s: skip update until corruption check "
			"is done (fg_skip_cnt:%d)\n",
			__func__, ++battery->fg_skip_cnt);
		fg_soc = battery->info.level;
		if (recover_flag || battery->fg_skip_cnt > 10) {
			battery->fg_skip = 0;
			battery->fg_skip_cnt = 0;
		}
	}

	if (battery->low_batt_boot_flag) {
		fg_soc = 0;

		if (check_ta_conn(battery) && !check_UV_charging_case()) {
			fg_adjust_capacity();
			battery->low_batt_boot_flag = 0;
		}

		if (!check_ta_conn(battery))
			battery->low_batt_boot_flag = 0;
	}

	fg_vcell = get_fuelgauge_value(FG_VOLTAGE);
	if (fg_vcell < 0) {
		pr_info("Can't read vcell!!!");
		fg_vcell = battery->info.batt_vol;
	} else
		battery->info.batt_vol = fg_vcell;

	fg_current = get_fuelgauge_value(FG_CURRENT);
#if !defined(CONFIG_MACH_SAMSUNG_P4) || !defined(CONFIG_MACH_SAMSUNG_P4WIFI) || !defined(CONFIG_MACH_SAMSUNG_P4LTE)
	avg_current = get_fuelgauge_value(FG_CURRENT_AVG);
	fg_vfsoc = get_fuelgauge_value(FG_VF_SOC);

	// Algorithm for reducing time to fully charged (from MAXIM)
	if(battery->info.charging_enabled &&  // Charging is enabled
		!battery->info.batt_is_recharging &&  // Not Recharging
		(battery->info.charging_source == CHARGER_AC ||
		(battery->info.charging_source == CHARGER_USB &&
		battery->info.force_usb_charging)) &&
		!battery->is_first_check &&  // Skip when first check after boot up
		(fg_vfsoc>70 && (fg_current>20 && fg_current<250) &&
		(avg_current>20 && avg_current<260))) {

		if(battery->full_check_flag == 2) {
			pr_info("%s: force fully charged SOC !! (%d)", __func__, battery->full_check_flag);
			fg_set_full_charged();
			fg_soc = get_fuelgauge_value(FG_LEVEL);
		}
		else if(battery->full_check_flag < 2)
			pr_info("%s: full_check_flag (%d)", __func__, battery->full_check_flag);

		if(battery->full_check_flag++ > 10000)  // prevent overflow
			battery->full_check_flag = 3;
	}
	else
		battery->full_check_flag = 0;
#endif

	if ((battery->info.charging_source == CHARGER_AC ||
		(battery->info.charging_source == CHARGER_USB &&
		battery->info.force_usb_charging)) &&
		battery->info.batt_improper_ta == 0) {
		if (is_over_abs_time(battery)) {
			fg_soc = 100;
			battery->info.batt_is_full = 1;
			pr_info("%s: charging time is over", __func__);
			pr_info("%s: fg_vcell = %d, fg_soc = %d,"
				" is_full = %d\n",
				__func__, fg_vcell, fg_soc,
				battery->info.batt_is_full);
			p3_set_chg_en(battery, 0);
			goto __end__;
		}
	}

	if (fg_vcell <= battery->pdata->recharge_voltage) {
		if (battery->info.batt_is_full &&
			!battery->info.charging_enabled) {
			if (++battery->recharging_cnt > 1) {
				pr_info("recharging(under full)");
				battery->info.batt_is_recharging = 1;
				p3_set_chg_en(battery, 1);
				battery->recharging_cnt = 0;
				pr_info("%s: fg_vcell = %d, fg_soc = %d,"
					" is_recharging = %d\n",
					__func__, fg_vcell, fg_soc,
					battery->info.batt_is_recharging);
			}
		} else
			battery->recharging_cnt = 0;
	} else
		battery->recharging_cnt = 0;

	if (fg_soc > 100)
		fg_soc = 100;

	/*  Checks vcell level and tries to compensate SOC if needed.*/
	/*  If jig cable is connected, then skip low batt compensation check. */
#ifdef CONFIG_TARGET_LOCALE_KOR
	pr_info("%s : chek point 1, cond: %d!\n",__func__, max17042_chip_data->low_comp_pre_cond);
	if (!check_jig_on() && !battery->info.charging_enabled 
		&& max17042_chip_data->low_comp_pre_cond == 0) {
		if (p3_low_batt_compensation(fg_soc, fg_vcell, fg_current) == 1)
			pr_info("error ");
	}

	 if(max17042_chip_data->pre_cond_ok == 1) {
		max17042_chip_data->low_comp_pre_cond = 1;
		pr_info("%s : schedule low batt compensation! pre_count(%d), pre_condition(%d)\n",
			__func__, max17042_chip_data->pre_cond_ok, max17042_chip_data->low_comp_pre_cond);
		wake_lock(&battery->low_comp_wake_lock);
		queue_delayed_work(battery->low_bat_comp_workqueue, &battery->low_comp_work, 0);
	}
#else
	if (!check_jig_on() && !battery->info.charging_enabled)
		fg_soc = p3_low_batt_compensation(fg_soc, fg_vcell, fg_current);
#endif

__end__:
	pr_debug("fg_vcell = %d, fg_soc = %d, is_full = %d",
		fg_vcell, fg_soc, battery->info.batt_is_full);

#if !defined(CONFIG_MACH_SAMSUNG_P4) || !defined(CONFIG_MACH_SAMSUNG_P4WIFI) || !defined(CONFIG_MACH_SAMSUNG_P4LTE)
	if(battery->is_first_check)
		battery->is_first_check = false;
#endif

	if (battery->info.batt_is_full &&
		(battery->info.charging_source != CHARGER_USB || battery->info.force_usb_charging))
		fg_soc = 100;
#if 0 // not used
	else {
		if (fg_soc >= 100)
			fg_soc = 99;
	}
#endif
	return fg_soc;
}
示例#8
0
static void asuspec_stresstest_work_function(struct work_struct *dat)
{
	asuspec_i2c_read_data(ec_chip->client);
	queue_delayed_work(asuspec_wq, &asuspec_stress_work, HZ/ec_chip->polling_rate);
}
示例#9
0
static int __devinit asuspec_probe(struct i2c_client *client,
		const struct i2c_device_id *id)
{
	int err = 0;

	ASUSPEC_INFO("asuspec probe\n");
	err = sysfs_create_group(&client->dev.kobj, &asuspec_smbus_group);
	if (err) {
		ASUSPEC_ERR("Unable to create the sysfs\n");
		goto exit;
	}

	ec_chip = kzalloc(sizeof (struct asuspec_chip), GFP_KERNEL);
	if (!ec_chip) {
		ASUSPEC_ERR("Memory allocation fails\n");
		err = -ENOMEM;
		goto exit;
	}
		
	i2c_set_clientdata(client, ec_chip);
	ec_chip->client = client;
	ec_chip->client->driver = &asuspec_driver;				
	ec_chip->client->flags = 1;

	init_timer(&ec_chip->asuspec_timer);
	ec_chip->asuspec_timer.function = asuspec_enter_s3_timer;

	wake_lock_init(&ec_chip->wake_lock, WAKE_LOCK_SUSPEND, "asuspec_wake");
	mutex_init(&ec_chip->lock);
	mutex_init(&ec_chip->irq_lock);
	mutex_init(&ec_chip->state_change_lock);

	ec_chip->ec_ram_init = 0;
	ec_chip->audio_recording = 0;
	ec_chip->status = 0;
	ec_chip->ec_in_s3 = 0;
	ec_chip->apwake_disabled = 0;
	asuspec_dockram_init(client);
	cdev_add(asuspec_cdev,asuspec_dev,1) ;

	ec_chip->pad_sdev.name = PAD_SDEV_NAME;
	ec_chip->pad_sdev.print_name = asuspec_switch_name;
	ec_chip->pad_sdev.print_state = asuspec_switch_state;
	if(switch_dev_register(&ec_chip->pad_sdev) < 0){
		ASUSPEC_ERR("switch_dev_register for pad failed!\n");
	}
	switch_set_state(&ec_chip->pad_sdev, 0);
	
	asuspec_wq = create_singlethread_workqueue("asuspec_wq");
	INIT_DELAYED_WORK_DEFERRABLE(&ec_chip->asuspec_work, asuspec_work_function);
	INIT_DELAYED_WORK_DEFERRABLE(&ec_chip->asuspec_init_work, asuspec_init_work_function);
	INIT_DELAYED_WORK_DEFERRABLE(&ec_chip->asuspec_fw_update_work, asuspec_fw_update_work_function);
	INIT_DELAYED_WORK_DEFERRABLE(&ec_chip->asuspec_enter_s3_work, asuspec_enter_s3_work_function);
	INIT_DELAYED_WORK_DEFERRABLE(&asuspec_stress_work, asuspec_stresstest_work_function);
	
	asuspec_irq_ec_request(client);
	asuspec_irq_ec_apwake(client);
	queue_delayed_work(asuspec_wq, &ec_chip->asuspec_init_work, 0);

	return 0;

exit:
	return err;
}
示例#10
0
/*
 * Internal function. Schedule delayed work in the MMC work queue.
 */
static int mmc_schedule_delayed_work(struct delayed_work *work,
				     unsigned long delay)
{
	return queue_delayed_work(workqueue, work, delay);
}
示例#11
0
static void asuspec_enter_s3_timer(unsigned long data){
	queue_delayed_work(asuspec_wq, &ec_chip->asuspec_enter_s3_work, 0);
}
示例#12
0
static int max8997_muic_probe(struct platform_device *pdev)
{
	struct max8997_dev *max8997 = dev_get_drvdata(pdev->dev.parent);
	struct max8997_platform_data *pdata = dev_get_platdata(max8997->dev);
	struct max8997_muic_info *info;
	int delay_jiffies;
	int ret, i;

	info = devm_kzalloc(&pdev->dev, sizeof(struct max8997_muic_info),
			    GFP_KERNEL);
	if (!info)
		return -ENOMEM;

	info->dev = &pdev->dev;
	info->muic = max8997->muic;

	platform_set_drvdata(pdev, info);
	mutex_init(&info->mutex);

	INIT_WORK(&info->irq_work, max8997_muic_irq_work);

	for (i = 0; i < ARRAY_SIZE(muic_irqs); i++) {
		struct max8997_muic_irq *muic_irq = &muic_irqs[i];
		unsigned int virq = 0;

		virq = irq_create_mapping(max8997->irq_domain, muic_irq->irq);
		if (!virq) {
			ret = -EINVAL;
			goto err_irq;
		}
		muic_irq->virq = virq;

		ret = request_threaded_irq(virq, NULL,
				max8997_muic_irq_handler,
				IRQF_NO_SUSPEND,
				muic_irq->name, info);
		if (ret) {
			dev_err(&pdev->dev,
				"failed: irq request (IRQ: %d, error :%d)\n",
				muic_irq->irq, ret);
			goto err_irq;
		}
	}

	/* External connector */
	info->edev = devm_extcon_dev_allocate(&pdev->dev, max8997_extcon_cable);
	if (IS_ERR(info->edev)) {
		dev_err(&pdev->dev, "failed to allocate memory for extcon\n");
		ret = -ENOMEM;
		goto err_irq;
	}

	ret = devm_extcon_dev_register(&pdev->dev, info->edev);
	if (ret) {
		dev_err(&pdev->dev, "failed to register extcon device\n");
		goto err_irq;
	}

	if (pdata && pdata->muic_pdata) {
		struct max8997_muic_platform_data *muic_pdata
			= pdata->muic_pdata;

		/* Initialize registers according to platform data */
		for (i = 0; i < muic_pdata->num_init_data; i++) {
			max8997_write_reg(info->muic,
					muic_pdata->init_data[i].addr,
					muic_pdata->init_data[i].data);
		}

		/*
		 * Default usb/uart path whether UART/USB or AUX_UART/AUX_USB
		 * h/w path of COMP2/COMN1 on CONTROL1 register.
		 */
		if (muic_pdata->path_uart)
			info->path_uart = muic_pdata->path_uart;
		else
			info->path_uart = CONTROL1_SW_UART;

		if (muic_pdata->path_usb)
			info->path_usb = muic_pdata->path_usb;
		else
			info->path_usb = CONTROL1_SW_USB;

		/*
		 * Default delay time for detecting cable state
		 * after certain time.
		 */
		if (muic_pdata->detcable_delay_ms)
			delay_jiffies =
				msecs_to_jiffies(muic_pdata->detcable_delay_ms);
		else
			delay_jiffies = msecs_to_jiffies(DELAY_MS_DEFAULT);
	} else {
		info->path_uart = CONTROL1_SW_UART;
		info->path_usb = CONTROL1_SW_USB;
		delay_jiffies = msecs_to_jiffies(DELAY_MS_DEFAULT);
	}

	/* Set initial path for UART */
	 max8997_muic_set_path(info, info->path_uart, true);

	/* Set ADC debounce time */
	max8997_muic_set_debounce_time(info, ADC_DEBOUNCE_TIME_25MS);

	/*
	 * Detect accessory after completing the initialization of platform
	 *
	 * - Use delayed workqueue to detect cable state and then
	 * notify cable state to notifiee/platform through uevent.
	 * After completing the booting of platform, the extcon provider
	 * driver should notify cable state to upper layer.
	 */
	INIT_DELAYED_WORK(&info->wq_detcable, max8997_muic_detect_cable_wq);
	queue_delayed_work(system_power_efficient_wq, &info->wq_detcable,
			delay_jiffies);

	return 0;

err_irq:
	while (--i >= 0)
		free_irq(muic_irqs[i].virq, info);
	return ret;
}
示例#13
0
/**
 * dwc3_otg_sm_work - workqueue function.
 *
 * @w: Pointer to the dwc3 otg workqueue
 *
 * NOTE: After any change in phy->state,
 * we must reschdule the state machine.
 */
static void dwc3_otg_sm_work(struct work_struct *w)
{
	struct dwc3_otg *dotg = container_of(w, struct dwc3_otg, sm_work.work);
	struct usb_phy *phy = dotg->otg.phy;
	struct dwc3_charger *charger = dotg->charger;
	bool work = 0;
	int ret = 0;
	unsigned long delay = 0;

	pm_runtime_resume(phy->dev);
	dev_info(phy->dev, "%s state\n", otg_state_string(phy->state));

	/* Check OTG state */
	switch (phy->state) {
	case OTG_STATE_UNDEFINED:
		dwc3_otg_init_sm(dotg);
		if (!dotg->psy) {
			dotg->psy = power_supply_get_by_name("usb");

			if (!dotg->psy)
				dev_err(phy->dev,
					 "couldn't get usb power supply\n");
		}

		/* Switch to A or B-Device according to ID / BSV */
		if (!test_bit(ID, &dotg->inputs)) {
			dev_dbg(phy->dev, "!id\n");
			phy->state = OTG_STATE_A_IDLE;
			work = 1;
		} else if (test_bit(B_SESS_VLD, &dotg->inputs)) {
			dev_dbg(phy->dev, "b_sess_vld\n");
			phy->state = OTG_STATE_B_IDLE;
			work = 1;
		} else {
			phy->state = OTG_STATE_B_IDLE;
			dev_dbg(phy->dev, "No device, trying to suspend\n");
			pm_runtime_put_sync(phy->dev);
		}
		break;

	case OTG_STATE_B_IDLE:
		if (!test_bit(ID, &dotg->inputs)) {
			dev_dbg(phy->dev, "!id\n");
			phy->state = OTG_STATE_A_IDLE;
			work = 1;
			dotg->charger_retry_count = 0;
			if (charger) {
				if (charger->chg_type == DWC3_INVALID_CHARGER)
					charger->start_detection(dotg->charger,
									false);
				else
					charger->chg_type =
							DWC3_INVALID_CHARGER;
			}
		} else if (test_bit(B_SESS_VLD, &dotg->inputs)) {
			dev_dbg(phy->dev, "b_sess_vld\n");
			if (charger) {
				/* Has charger been detected? If no detect it */
				switch (charger->chg_type) {
				case DWC3_DCP_CHARGER:
				case DWC3_PROPRIETARY_CHARGER:
					dev_dbg(phy->dev, "lpm, DCP charger\n");
					dwc3_otg_set_power(phy,
							DWC3_IDEV_CHG_MAX);
					pm_runtime_put_sync(phy->dev);
					break;
				case DWC3_CDP_CHARGER:
					dwc3_otg_set_power(phy,
							DWC3_IDEV_CHG_MAX);
					dwc3_otg_start_peripheral(&dotg->otg,
									1);
					phy->state = OTG_STATE_B_PERIPHERAL;
					work = 1;
					break;
				case DWC3_SDP_CHARGER:
					dwc3_otg_start_peripheral(&dotg->otg,
									1);
					phy->state = OTG_STATE_B_PERIPHERAL;
					work = 1;
					break;
				case DWC3_FLOATED_CHARGER:
					if (dotg->charger_retry_count <
							max_chgr_retry_count)
						dotg->charger_retry_count++;
					/*
					 * In case of floating charger, if
					 * retry count equal to max retry count
					 * notify PMIC about floating charger
					 * and put Hw in low power mode. Else
					 * perform charger detection again by
					 * calling start_detection() with false
					 * and then with true argument.
					 */
					if (dotg->charger_retry_count ==
						max_chgr_retry_count) {
						dwc3_otg_set_power(phy, 0);
						qpnp_chg_notify_invalid_usb();
						pm_runtime_put_sync(phy->dev);
						break;
					}
					charger->start_detection(dotg->charger,
									false);

				default:
					dev_dbg(phy->dev, "chg_det started\n");
					charger->start_detection(charger, true);
					break;
				}
			} else {
				/* no charger registered, start peripheral */
				if (dwc3_otg_start_peripheral(&dotg->otg, 1)) {
					/*
					 * Probably set_peripheral not called
					 * yet. We will re-try as soon as it
					 * will be called
					 */
					dev_err(phy->dev, "enter lpm as\n"
						"unable to start B-device\n");
					phy->state = OTG_STATE_UNDEFINED;
					pm_runtime_put_sync(phy->dev);
					return;
				}
			}
		} else {
			if (charger)
				charger->start_detection(dotg->charger, false);

			dotg->charger_retry_count = 0;
			dwc3_otg_set_power(phy, 0);
			dev_dbg(phy->dev, "No device, trying to suspend\n");
			pm_runtime_put_sync(phy->dev);
		}
		break;

	case OTG_STATE_B_PERIPHERAL:
		if (!test_bit(B_SESS_VLD, &dotg->inputs) ||
				!test_bit(ID, &dotg->inputs)) {
			dev_dbg(phy->dev, "!id || !bsv\n");
			dwc3_otg_start_peripheral(&dotg->otg, 0);
			phy->state = OTG_STATE_B_IDLE;
			if (charger)
				charger->chg_type = DWC3_INVALID_CHARGER;
			work = 1;
		}
		break;

	case OTG_STATE_A_IDLE:
		/* Switch to A-Device*/
		if (test_bit(ID, &dotg->inputs)) {
			dev_dbg(phy->dev, "id\n");
			phy->state = OTG_STATE_B_IDLE;
			dotg->vbus_retry_count = 0;
			work = 1;
			clear_bit(A_VBUS_DROP_DET, &dotg->inputs);
		} else if (test_bit(A_VBUS_DROP_DET, &dotg->inputs)) {
			dev_dbg(phy->dev, "vbus_drop_det\n");
			/* staying on here until exit from A-Device */
		} else {
			phy->state = OTG_STATE_A_HOST;
			ret = dwc3_otg_start_host(&dotg->otg, 1);
			if ((ret == -EPROBE_DEFER) &&
						dotg->vbus_retry_count < 3) {
				/*
				 * Get regulator failed as regulator driver is
				 * not up yet. Will try to start host after 1sec
				 */
				phy->state = OTG_STATE_A_IDLE;
				dev_dbg(phy->dev, "Unable to get vbus regulator. Retrying...\n");
				delay = VBUS_REG_CHECK_DELAY;
				work = 1;
				dotg->vbus_retry_count++;
			} else if (ret) {
				/*
				 * Probably set_host was not called yet.
				 * We will re-try as soon as it will be called
				 */
				dev_dbg(phy->dev, "enter lpm as\n"
					"unable to start A-device\n");
				phy->state = OTG_STATE_A_IDLE;
				pm_runtime_put_sync(phy->dev);
				return;
			}
		}
		break;

	case OTG_STATE_A_HOST:
		if (test_bit(ID, &dotg->inputs)) {
			dev_dbg(phy->dev, "id\n");
			dwc3_otg_start_host(&dotg->otg, 0);
			phy->state = OTG_STATE_B_IDLE;
			dotg->vbus_retry_count = 0;
			work = 1;
			clear_bit(A_VBUS_DROP_DET, &dotg->inputs);
		} else if (test_bit(A_VBUS_DROP_DET, &dotg->inputs)) {
			dev_dbg(phy->dev, "vbus_drop_det\n");
			dwc3_otg_start_host(&dotg->otg, 0);
			phy->state = OTG_STATE_A_IDLE;
			work = 1;
#ifdef CONFIG_USB_HOST_EXTRA_NOTIFICATION
			host_send_uevent(USB_HOST_EXT_EVENT_VBUS_DROP);
#endif
		}
		break;

	default:
		dev_err(phy->dev, "%s: invalid otg-state\n", __func__);

	}

	if (work)
		queue_delayed_work(system_nrt_wq, &dotg->sm_work, delay);
}
示例#14
0
/**
 * dwc3_ext_event_notify - callback to handle events from external transceiver
 * @otg: Pointer to the otg transceiver structure
 * @event: Event reported by transceiver
 *
 * Returns 0 on success
 */
static void dwc3_ext_event_notify(struct usb_otg *otg,
					enum dwc3_ext_events event)
{
	static bool init;
	struct dwc3_otg *dotg = container_of(otg, struct dwc3_otg, otg);
	struct dwc3_ext_xceiv *ext_xceiv = dotg->ext_xceiv;
	struct usb_phy *phy = dotg->otg.phy;
	int ret = 0;

	/* Flush processing any pending events before handling new ones */
	if (init)
		flush_delayed_work(&dotg->sm_work);

	if (event == DWC3_EVENT_PHY_RESUME) {
		if (!pm_runtime_status_suspended(phy->dev)) {
			dev_warn(phy->dev, "PHY_RESUME event out of LPM!!!!\n");
		} else {
			dev_dbg(phy->dev, "ext PHY_RESUME event received\n");
			/* ext_xceiver would have taken h/w out of LPM by now */
			ret = pm_runtime_get(phy->dev);
			if ((phy->state == OTG_STATE_A_HOST) &&
							dotg->host_bus_suspend)
				dotg->host_bus_suspend = 0;
			if (ret == -EACCES) {
				/* pm_runtime_get may fail during system
				   resume with -EACCES error */
				pm_runtime_disable(phy->dev);
				pm_runtime_set_active(phy->dev);
				pm_runtime_enable(phy->dev);
			} else if (ret < 0) {
				dev_warn(phy->dev, "pm_runtime_get failed!\n");
			}
		}
	} else if (event == DWC3_EVENT_XCEIV_STATE) {
		if (pm_runtime_status_suspended(phy->dev)) {
			dev_warn(phy->dev, "PHY_STATE event in LPM!!!!\n");
			ret = pm_runtime_get(phy->dev);
			if (ret < 0)
				dev_warn(phy->dev, "pm_runtime_get failed!!\n");
		}
		if (ext_xceiv->id == DWC3_ID_FLOAT) {
			dev_info(phy->dev, "XCVR: ID set\n");
			set_bit(ID, &dotg->inputs);
		} else {
			dev_info(phy->dev, "XCVR: ID clear\n");
			clear_bit(ID, &dotg->inputs);
		}

		if (ext_xceiv->bsv) {
			dev_info(phy->dev, "XCVR: BSV set\n");
			set_bit(B_SESS_VLD, &dotg->inputs);
		} else {
			dev_info(phy->dev, "XCVR: BSV clear\n");
			clear_bit(B_SESS_VLD, &dotg->inputs);
		}

		if (ext_xceiv->ocp) {
			dev_dbg(phy->dev, "XCVR: OCP set\n");
			ext_xceiv->ocp = false;
			set_bit(A_VBUS_DROP_DET, &dotg->inputs);
		}

		if (!init) {
			init = true;
			if (!work_busy(&dotg->sm_work.work))
				queue_delayed_work(system_nrt_wq,
							&dotg->sm_work, 0);

			complete(&dotg->dwc3_xcvr_vbus_init);
			dev_dbg(phy->dev, "XCVR: BSV init complete\n");
			return;
		}

		queue_delayed_work(system_nrt_wq, &dotg->sm_work, 0);
	}
}
示例#15
0
static void pm8xxx_led_current_set_flagged(struct led_classdev *led_cdev, enum led_brightness brightness, int blink)
{
	struct pm8xxx_led_data *led = container_of(led_cdev,  struct pm8xxx_led_data, cdev);
	int rc, offset;
	u8 level;

	int *pduties;

	LED_INFO("%s, bank:%d, brightness:%d\n", __func__, led->bank, brightness);
	cancel_delayed_work_sync(&led->fade_delayed_work);
	virtual_key_state = brightness;
	if (flag_hold_virtual_key == 1) {
		LED_INFO("%s, key control \n", __func__);
		return;
	}

	if(brightness) {
		level = (led->out_current << PM8XXX_DRV_LED_CTRL_SHIFT) & PM8XXX_DRV_LED_CTRL_MASK;
		offset = PM8XXX_LED_OFFSET(led->id);
		led->reg &= ~PM8XXX_DRV_LED_CTRL_MASK;
		led->reg |= level;
		rc = pm8xxx_writeb(led->dev->parent, SSBI_REG_ADDR_LED_CTRL(offset), led->reg);
		if (rc)
			LED_ERR("%s can't set (%d) led value rc=%d\n", __func__, led->id, rc);

		if (led->function_flags & LED_BRETH_FUNCTION) {

			if (blink == 0)
			{
				buttons_led_is_on = 1;
				// no blink needed
				pduties = led->duties;
				pm8xxx_pwm_lut_config(led->pwm_led,
							led->period_us,
							pduties,
							led->duty_time_ms,
							led->start_index,
							led->duites_size,
							0, 0,
							led->lut_flag);
			} else
			{
				pduties = led->duties;
				// LUT_LOOP for blinking
				pm8xxx_pwm_lut_config(led->pwm_led,
							led->period_us,
							pduties,
							led->duty_time_ms, // slower, 2x
							led->start_index,
							led->duites_size * 8, // 16 duty entries -> original size * 2, + 6 * 8 zeroes for pause
							0, 0,
							PM_PWM_LUT_LOOP | PM_PWM_LUT_PAUSE_HI_EN);
			}

			pm8xxx_pwm_lut_enable(led->pwm_led, 0);
			pm8xxx_pwm_lut_enable(led->pwm_led, 1);
		} else {
			pwm_config(led->pwm_led, 64000, 64000);
			pwm_enable(led->pwm_led);
		}
	} else {
		if (led->function_flags & LED_BRETH_FUNCTION) {
			buttons_led_is_on = 0;
			wake_lock_timeout(&pmic_led_wake_lock, HZ*2);
			pduties = led->duties + led->duites_size;
			pm8xxx_pwm_lut_config(led->pwm_led,
						led->period_us,
						pduties,
						led->duty_time_ms,
						led->start_index,
						led->duites_size,
						0, 0,
						led->lut_flag);
			pm8xxx_pwm_lut_enable(led->pwm_led, 0);
			pm8xxx_pwm_lut_enable(led->pwm_led, 1);
			queue_delayed_work(g_led_work_queue,
						&led->fade_delayed_work,
						msecs_to_jiffies(led->duty_time_ms*led->duites_size));
		} else {
			pwm_disable(led->pwm_led);
			level = (0 << PM8XXX_DRV_LED_CTRL_SHIFT) & PM8XXX_DRV_LED_CTRL_MASK;
			offset = PM8XXX_LED_OFFSET(led->id);
			led->reg &= ~PM8XXX_DRV_LED_CTRL_MASK;
			led->reg |= level;
			rc = pm8xxx_writeb(led->dev->parent, SSBI_REG_ADDR_LED_CTRL(offset), led->reg);
			if (rc)
				LED_ERR("%s can't set (%d) led value rc=%d\n", __func__, led->id, rc);
		}
	}
}
/*
 * tuple format: (key_code, key_param)
 *
 * old-architecture:
 * key-press = (key_code, 0)
 * key-release = (0xff, key_code)
 *
 * new-architecutre:
 * key-press = (key_code, 0)
 * key-release = (key_code, 0xff)
 */
static void report_hs_key(uint32_t key_code, uint32_t key_parm)
{
	int key, temp_key_code;

	printk("+%s %d+\n",__func__,__LINE__);
	if (key_code == HS_REL_K)
		key = hs_find_key(key_parm);
	else
		key = hs_find_key(key_code);

	temp_key_code = key_code;

	if (key_parm == HS_REL_K)
		key_code = key_parm;

	switch (key) {
	case KEY_POWER:
	case KEY_END:
		key = KEY_POWER;
	case KEY_MEDIA:
	case KEY_VOLUMEUP:
	case KEY_VOLUMEDOWN:
		input_report_key(hs->ipdev, key, (key_code != HS_REL_K));
		printk("%s %d report pwr key\n",__func__,__LINE__);
    {
      if(key == KEY_POWER)
      {
        if(key_code == HS_REL_K)
        {
          pwrkey_down = 0;
          cancel_delayed_work_sync(&pwrkey_work);
        }
        else
        {
          pwrkey_down = 1;
          queue_delayed_work(pwrkey_wqueue, &pwrkey_work, 8*HZ);
        }
      }
      else if(key == KEY_END && pwrkey_down == 1)
      {
        if(key_code == HS_REL_K)
        {
          pwrkey_down = 0;
          cancel_delayed_work_sync(&pwrkey_work);
        }
      }
    }
	
		break;
	case SW_HEADPHONE_INSERT_W_MIC:
		hs->mic_on = hs->hs_on = (key_code != HS_REL_K) ? 1 : 0;
		input_report_switch(hs->ipdev, SW_HEADPHONE_INSERT,
							hs->hs_on);
		input_report_switch(hs->ipdev, SW_MICROPHONE_INSERT,
							hs->mic_on);
		update_state();
		break;

	case SW_HEADPHONE_INSERT:
		hs->hs_on = (key_code != HS_REL_K) ? 1 : 0;
		input_report_switch(hs->ipdev, key, hs->hs_on);
		update_state();
		break;
	case SW_MICROPHONE_INSERT:
		hs->mic_on = (key_code != HS_REL_K) ? 1 : 0;
		input_report_switch(hs->ipdev, key, hs->mic_on);
		update_state();
		break;
  case KEY_BATTERY:
    #ifdef CONFIG_BATTERY_QSD
    if(key_code == HS_BAD_BATT_K)
    {
      qsd_bat_update_usb_status(CHG_EVENT_GAGIC_BATT_GOOD);
    }
    else if(key_code == HS_CHARGING_ON_K)
    {
      qsd_bat_update_usb_status(AC_STATUS_AC_IN);
#ifdef CONFIG_HW_AUSTIN	  
      q6audio_update_AC_5V_status(1);
#endif //CONFIG_HW_AUSTIN
    }	  
    else if(key_code == HS_CHARGING_OFF_K)
    {
      qsd_bat_update_usb_status(AC_STATUS_AC_NONE);
#ifdef CONFIG_HW_AUSTIN	  
      q6audio_update_AC_5V_status(0);	
#endif //CONFIG_HW_AUSTIN
    }
    else if(key_code == HS_BAT_LOW_K)
    {
      qsd_bat_update_usb_status(CHG_EVENT_PMIC_BATT_LOW);
    }
    #endif
	printk("-%s ret bat %d-\n",__func__,__LINE__);
    return; //break;
	case -1:
		printk(KERN_ERR "%s: No mapping for remote handset event %d\n",
				 __func__, temp_key_code);
		printk("-%s ret -1 %d-\n",__func__,__LINE__);
		return;
	}
	input_sync(hs->ipdev);
	printk("-%s ret normal %d-\n",__func__,__LINE__);
}
示例#17
0
static ssize_t pm8xxx_led_blink_store(struct device *dev,
				       struct device_attribute *attr,
				       const char *buf, size_t count)
{
	struct led_classdev *led_cdev;
	struct pm8xxx_led_data *ldata;
	int val;
	int level, offset;

	val = -1;
	sscanf(buf, "%u", &val);
	if (val < 0 || val > 255)
		return -EINVAL;
	current_blink= val;
	led_cdev = (struct led_classdev *) dev_get_drvdata(dev);
	ldata = container_of(led_cdev, struct pm8xxx_led_data, cdev);

	LED_INFO("%s: bank %d blink %d sync %d\n", __func__, ldata->bank, val, ldata->led_sync);
	printk("[BB] blink value: %d\n",val);

	switch (val) {
	case BLINK_STOP:
		if (ldata->gpio_status_switch != NULL)
			ldata->gpio_status_switch(0);
		pwm_disable(ldata->pwm_led);

		if(ldata->led_sync) {
			if 	(!strcmp(ldata->cdev.name, "green")) {
				if (green_back_led_data->gpio_status_switch != NULL)
					green_back_led_data->gpio_status_switch(0);
				pwm_disable(green_back_led_data->pwm_led);
			}
			if 	(!strcmp(ldata->cdev.name, "amber")) {
				if (amber_back_led_data->gpio_status_switch != NULL)
					amber_back_led_data->gpio_status_switch(0);
				pwm_disable(amber_back_led_data->pwm_led);
			}
		}
		if (bln > 0)
		{
			pm8xxx_buttons_blink(0);
		}
		break;
	case BLINK_UNCHANGE:
		pwm_disable(ldata->pwm_led);
		if (led_cdev->brightness) {
			if (ldata->gpio_status_switch != NULL)
				ldata->gpio_status_switch(1);
			pwm_config(ldata->pwm_led, 6400 * ldata->pwm_coefficient / 100, 6400);
			pwm_enable(ldata->pwm_led);

			if(ldata->led_sync) {
				if	(!strcmp(ldata->cdev.name, "green")) {
					if (green_back_led_data->gpio_status_switch != NULL)
						green_back_led_data->gpio_status_switch(1);
					pwm_config(green_back_led_data->pwm_led, 64000, 64000);
					pwm_enable(green_back_led_data->pwm_led);
				}
				if	(!strcmp(ldata->cdev.name, "amber")) {
					if (amber_back_led_data->gpio_status_switch != NULL)
						amber_back_led_data->gpio_status_switch(1);
					pwm_config(amber_back_led_data->pwm_led, 64000, 64000);
					pwm_enable(amber_back_led_data->pwm_led);
				}
			}
			if (bln > 0 && val > 0)
			{
				pm8xxx_buttons_blink(1);
			}
		} else {
			pwm_disable(ldata->pwm_led);
			if (ldata->gpio_status_switch != NULL)
				ldata->gpio_status_switch(0);

			if(ldata->led_sync) {
				if (!strcmp(ldata->cdev.name, "green")){
					if (green_back_led_data->gpio_status_switch != NULL)
						green_back_led_data->gpio_status_switch(0);
					pwm_disable(green_back_led_data->pwm_led);
					level = ( 0 << PM8XXX_DRV_LED_CTRL_SHIFT) & PM8XXX_DRV_LED_CTRL_MASK;
					offset = PM8XXX_LED_OFFSET(green_back_led_data->id);
					green_back_led_data->reg &= ~PM8XXX_DRV_LED_CTRL_MASK;
					green_back_led_data->reg |= level;
					pm8xxx_writeb(green_back_led_data->dev->parent, SSBI_REG_ADDR_LED_CTRL(offset), green_back_led_data->reg);
				}
				if (!strcmp(ldata->cdev.name, "amber")){
					if (amber_back_led_data->gpio_status_switch != NULL)
						amber_back_led_data->gpio_status_switch(0);
					pwm_disable(amber_back_led_data->pwm_led);
					level = ( 0 << PM8XXX_DRV_LED_CTRL_SHIFT) & PM8XXX_DRV_LED_CTRL_MASK;
					offset = PM8XXX_LED_OFFSET(amber_back_led_data->id);
					amber_back_led_data->reg &= ~PM8XXX_DRV_LED_CTRL_MASK;
					amber_back_led_data->reg |= level;
					pm8xxx_writeb(amber_back_led_data->dev->parent, SSBI_REG_ADDR_LED_CTRL(offset), amber_back_led_data->reg);
				}
			}
			if (bln > 0)
			{
				pm8xxx_buttons_blink(0);
			}
		}
		break;
	case BLINK_64MS_PER_2SEC:
		if (ldata->gpio_status_switch != NULL)
			ldata->gpio_status_switch(1);
		pwm_disable(ldata->pwm_led);
		pwm_config(ldata->pwm_led, 64000, 2000000);
		pwm_enable(ldata->pwm_led);

		if(ldata->led_sync) {
			if	(!strcmp(ldata->cdev.name, "green")) {
				if (green_back_led_data->gpio_status_switch != NULL)
					green_back_led_data->gpio_status_switch(1);
				pwm_disable(green_back_led_data->pwm_led);
				pwm_config(green_back_led_data->pwm_led, 64000, 2000000);
				pwm_enable(green_back_led_data->pwm_led);
			}
			if	(!strcmp(ldata->cdev.name, "amber")) {
				if (amber_back_led_data->gpio_status_switch != NULL)
					amber_back_led_data->gpio_status_switch(1);
				pwm_disable(amber_back_led_data->pwm_led);
				pwm_config(amber_back_led_data->pwm_led, 64000, 2000000);
				pwm_enable(amber_back_led_data->pwm_led);
			}
		}
		if (bln > 0 && val > 0)
		{
			pm8xxx_buttons_blink(1);
		}
		break;
	case BLINK_64MS_ON_310MS_PER_2SEC:
		cancel_delayed_work_sync(&ldata->blink_delayed_work);
		pwm_disable(ldata->pwm_led);
		ldata->duty_time_ms = 64;
		ldata->period_us = 2000000;

		if(ldata->led_sync) {
			if	(!strcmp(ldata->cdev.name, "green")) {
				pwm_disable(green_back_led_data->pwm_led);
				green_back_led_data->duty_time_ms = 64;
				green_back_led_data->period_us = 2000000;
			}
			if	(!strcmp(ldata->cdev.name, "amber")) {
				pwm_disable(amber_back_led_data->pwm_led);
				amber_back_led_data->duty_time_ms = 64;
				amber_back_led_data->period_us = 2000000;
			}
		}
		queue_delayed_work(g_led_work_queue, &ldata->blink_delayed_work,
				   msecs_to_jiffies(310));
		break;
	case BLINK_64MS_ON_2SEC_PER_2SEC:
		cancel_delayed_work_sync(&ldata->blink_delayed_work);
		pwm_disable(ldata->pwm_led);
		ldata->duty_time_ms = 64;
		ldata->period_us = 2000000;

		if(ldata->led_sync) {
			if	(!strcmp(ldata->cdev.name, "green")) {
				pwm_disable(green_back_led_data->pwm_led);
				green_back_led_data->duty_time_ms = 64;
				green_back_led_data->period_us = 2000000;
			}
			if	(!strcmp(ldata->cdev.name, "amber")) {
				pwm_disable(amber_back_led_data->pwm_led);
				amber_back_led_data->duty_time_ms = 64;
				amber_back_led_data->period_us = 2000000;
			}
		}
		queue_delayed_work(g_led_work_queue, &ldata->blink_delayed_work,
				   msecs_to_jiffies(1000));
		break;
	case BLINK_1SEC_PER_2SEC:
		pwm_disable(ldata->pwm_led);
		pwm_config(ldata->pwm_led, 1000000, 2000000);
		pwm_enable(ldata->pwm_led);

		if(ldata->led_sync) {
			if	(!strcmp(ldata->cdev.name, "green")) {
				pwm_disable(green_back_led_data->pwm_led);
				pwm_config(green_back_led_data->pwm_led, 1000000, 2000000);
				pwm_enable(green_back_led_data->pwm_led);
			}
			if	(!strcmp(ldata->cdev.name, "amber")) {
				pwm_disable(amber_back_led_data->pwm_led);
				pwm_config(amber_back_led_data->pwm_led, 1000000, 2000000);
				pwm_enable(amber_back_led_data->pwm_led);
			}
		}
		break;
	default:
		LED_ERR("%s: bank %d did not support blink type %d\n", __func__, ldata->bank, val);
		return -EINVAL;
	}

	return count;
}
static void usb_rx_retry_work(struct work_struct *work)
{
	int ret = 0;
	struct usb_link_device *usb_ld =
		container_of(work, struct usb_link_device, rx_retry_work.work);
	struct urb *urb = usb_ld->retry_urb;
	struct if_usb_devdata *pipe_data = urb->context;
	struct io_device *iod;
	int iod_format;

	if (!usb_ld->if_usb_connected || !usb_ld->usbdev)
		return;

	if (usb_ld->usbdev)
		usb_mark_last_busy(usb_ld->usbdev);
	switch (pipe_data->format) {
	case IF_USB_FMT_EP:
		if (usb_ld->if_usb_is_main) {
			pr_urb("IPC-RX, retry", urb);
			iod_format = IPC_FMT;
		} else {
			iod_format = IPC_BOOT;
		}
		break;
	case IF_USB_RAW_EP:
		iod_format = IPC_MULTI_RAW;
		break;
	case IF_USB_RFS_EP:
		iod_format = IPC_RFS;
		pr_urb("RFS-RX, retry", urb);
		break;
	case IF_USB_CMD_EP:
		iod_format = IPC_CMD;
		break;
	default:
		iod_format = -1;
		break;
	}

	iod = link_get_iod_with_format(&usb_ld->ld, iod_format);
	if (iod) {
		ret = iod->recv(iod, &usb_ld->ld, (char *)urb->transfer_buffer,
			urb->actual_length);
		if (ret == -ENOMEM) {
			/* TODO: check the retry count */
			/* retry the delay work after 20ms and resubit*/
			mif_err("ENOMEM, +retry 20ms\n");
			if (usb_ld->usbdev)
				usb_mark_last_busy(usb_ld->usbdev);
			usb_ld->retry_urb = urb;
			if (usb_ld->rx_retry_cnt++ < 10)
				queue_delayed_work(usb_ld->ld.tx_wq,
					&usb_ld->rx_retry_work,	10);
			return;
		}
		if (ret < 0)
			mif_err("io device recv error (%d)\n", ret);
		usb_ld->rx_retry_cnt = 0;
	}

	if (usb_ld->usbdev)
		usb_mark_last_busy(usb_ld->usbdev);
	usb_rx_submit(usb_ld, pipe_data, GFP_ATOMIC);
}
示例#19
0
static int set_guid_rec(struct ib_device *ibdev,
			u8 port, int index,
			struct mlx4_sriov_alias_guid_info_rec_det *rec_det)
{
	int err;
	struct mlx4_ib_dev *dev = to_mdev(ibdev);
	struct ib_sa_guidinfo_rec guid_info_rec;
	ib_sa_comp_mask comp_mask;
	struct ib_port_attr attr;
	struct mlx4_alias_guid_work_context *callback_context;
	unsigned long resched_delay, flags, flags1;
	struct list_head *head =
		&dev->sriov.alias_guid.ports_guid[port - 1].cb_list;

	err = __mlx4_ib_query_port(ibdev, port, &attr, 1);
	if (err) {
		pr_debug("mlx4_ib_query_port failed (err: %d), port: %d\n",
			 err, port);
		return err;
	}
	/*check the port was configured by the sm, otherwise no need to send */
	if (attr.state != IB_PORT_ACTIVE) {
		pr_debug("port %d not active...rescheduling\n", port);
		resched_delay = 5 * HZ;
		err = -EAGAIN;
		goto new_schedule;
	}

	callback_context = kmalloc(sizeof *callback_context, GFP_KERNEL);
	if (!callback_context) {
		err = -ENOMEM;
		resched_delay = HZ * 5;
		goto new_schedule;
	}
	callback_context->port = port;
	callback_context->dev = dev;
	callback_context->block_num = index;

	memset(&guid_info_rec, 0, sizeof (struct ib_sa_guidinfo_rec));

	guid_info_rec.lid = cpu_to_be16(attr.lid);
	guid_info_rec.block_num = index;

	memcpy(guid_info_rec.guid_info_list, rec_det->all_recs,
	       GUID_REC_SIZE * NUM_ALIAS_GUID_IN_REC);
	comp_mask = IB_SA_GUIDINFO_REC_LID | IB_SA_GUIDINFO_REC_BLOCK_NUM |
		rec_det->guid_indexes;

	init_completion(&callback_context->done);
	spin_lock_irqsave(&dev->sriov.alias_guid.ag_work_lock, flags1);
	list_add_tail(&callback_context->list, head);
	spin_unlock_irqrestore(&dev->sriov.alias_guid.ag_work_lock, flags1);

	callback_context->query_id =
		ib_sa_guid_info_rec_query(dev->sriov.alias_guid.sa_client,
					  ibdev, port, &guid_info_rec,
					  comp_mask, rec_det->method, 1000,
					  GFP_KERNEL, aliasguid_query_handler,
					  callback_context,
					  &callback_context->sa_query);
	if (callback_context->query_id < 0) {
		pr_debug("ib_sa_guid_info_rec_query failed, query_id: "
			 "%d. will reschedule to the next 1 sec.\n",
			 callback_context->query_id);
		spin_lock_irqsave(&dev->sriov.alias_guid.ag_work_lock, flags1);
		list_del(&callback_context->list);
		kfree(callback_context);
		spin_unlock_irqrestore(&dev->sriov.alias_guid.ag_work_lock, flags1);
		resched_delay = 1 * HZ;
		err = -EAGAIN;
		goto new_schedule;
	}
	err = 0;
	goto out;

new_schedule:
	spin_lock_irqsave(&dev->sriov.going_down_lock, flags);
	spin_lock_irqsave(&dev->sriov.alias_guid.ag_work_lock, flags1);
	invalidate_guid_record(dev, port, index);
	if (!dev->sriov.is_going_down) {
		queue_delayed_work(dev->sriov.alias_guid.ports_guid[port - 1].wq,
				   &dev->sriov.alias_guid.ports_guid[port - 1].alias_guid_work,
				   resched_delay);
	}
	spin_unlock_irqrestore(&dev->sriov.alias_guid.ag_work_lock, flags1);
	spin_unlock_irqrestore(&dev->sriov.going_down_lock, flags);

out:
	return err;
}
static void usb_rx_complete(struct urb *urb)
{
	struct if_usb_devdata *pipe_data = urb->context;
	struct usb_link_device *usb_ld = pipe_data->usb_ld;
	struct io_device *iod;
	int iod_format;
	int ret;

	if (usb_ld->usbdev)
		usb_mark_last_busy(usb_ld->usbdev);

	switch (urb->status) {
	case -ENOENT:
		/* case for 'link pm suspended but rx data had remained' */
		mif_debug("urb->status = -ENOENT\n");
	case 0:
		if (!urb->actual_length) {
			mif_debug("urb has zero length!\n");
			goto rx_submit;
		}

		usb_ld->link_pm_data->rx_cnt++;
		/* call iod recv */
		/* how we can distinguish boot ch with fmt ch ?? */
		switch (pipe_data->format) {
		case IF_USB_FMT_EP:
			if (usb_ld->if_usb_is_main) {
#if 0
				pr_urb("IPC-RX", urb);
#endif
				iod_format = IPC_FMT;
			} else {
				iod_format = IPC_BOOT;
			}
			break;
		case IF_USB_RAW_EP:
			iod_format = IPC_MULTI_RAW;
			break;
		case IF_USB_RFS_EP:
			iod_format = IPC_RFS;
			break;
		case IF_USB_CMD_EP:
			iod_format = IPC_CMD;
			break;
		default:
			iod_format = -1;
			break;
		}

		/* flow control CMD by CP, not use io device */
		if (unlikely(iod_format == IPC_CMD)) {
			ret = link_rx_flowctl_cmd(&usb_ld->ld,
					(char *)urb->transfer_buffer,
					urb->actual_length);
			if (ret < 0)
				mif_err("no multi raw device (%d)\n", ret);
			goto rx_submit;
		}

		iod = link_get_iod_with_format(&usb_ld->ld, iod_format);
		if (iod) {
			ret = iod->recv(iod,
					&usb_ld->ld,
					(char *)urb->transfer_buffer,
					urb->actual_length);
			if (ret == -ENOMEM) {
				/* retry the delay work and resubit*/
				mif_err("ENOMEM, retry\n");
				if (usb_ld->usbdev)
					usb_mark_last_busy(usb_ld->usbdev);
				usb_ld->retry_urb = urb;
				queue_delayed_work(usb_ld->ld.tx_wq,
					&usb_ld->rx_retry_work, 0);
				return;
			}
			if (ret < 0)
				mif_err("io device recv error (%d)\n", ret);
		}
rx_submit:
		if (urb->status == 0) {
			if (usb_ld->usbdev)
				usb_mark_last_busy(usb_ld->usbdev);
			usb_rx_submit(usb_ld, pipe_data, GFP_ATOMIC);
		}
		break;
	default:
		mif_err("urb err status = %d\n", urb->status);
		break;
	}
}
示例#21
0
/*
 * Internal function. Schedule delayed work in the MMC work queue.
 */
static int mmc_schedule_delayed_work(struct delayed_work *work,
				     unsigned long delay)
{
	wake_lock(&mmc_delayed_work_wake_lock);
	return queue_delayed_work(workqueue, work, delay);
}
static void usb_tx_work(struct work_struct *work)
{
	int ret = 0;
	struct link_device *ld =
		container_of(work, struct link_device, tx_delayed_work.work);
	struct usb_link_device *usb_ld = to_usb_link_device(ld);
	struct sk_buff *skb;
	struct link_pm_data *pm_data = usb_ld->link_pm_data;

	if (!usb_ld->usbdev) {
		mif_info("usbdev is invalid\n");
		return;
	}

	pm_data->tx_cnt++;

	while (ld->sk_fmt_tx_q.qlen || ld->sk_raw_tx_q.qlen) {
		/* request and check usb runtime pm first */
		ret = link_pm_runtime_get_active(pm_data);
		if (ret < 0) {
			if (ret == -ENODEV) {
				mif_err("link not avail, retry reconnect.\n");
				goto exit;
			}
			goto retry_tx_work;
		}

		/* If AP try to tx when interface disconnect->reconnect probe,
		 * usbdev was created but one of interface channel device are
		 * probing, _usb_tx_work return to -ENOENT then runtime usage
		 * count allways positive and never enter to L2
		 */
		if (!usb_ld->if_usb_connected_last) {
			mif_info("link is available, but if  was not readey\n");
			goto retry_tx_work;
		}
		pm_runtime_get_sync(&usb_ld->usbdev->dev);

		ret = 0;
		/* send skb from fmt_txq and raw_txq,*/
		/* one by one for fair flow control */
		skb = skb_dequeue(&ld->sk_fmt_tx_q);
		if (skb)
			ret = _usb_tx_work(skb);

		if (ret) {
			mif_err("usb_tx_urb_with_skb for fmt_q %d\n", ret);
			skb_queue_head(&ld->sk_fmt_tx_q, skb);

			if (ret == -ENODEV || ret == -ENOENT)
				goto exit;

			/* tx fail and usbdev alived, retry tx work */
			pm_runtime_put(&usb_ld->usbdev->dev);
			goto retry_tx_work;
		}

		skb = skb_dequeue(&ld->sk_raw_tx_q);
		if (skb)
			ret = _usb_tx_work(skb);

		if (ret) {
			mif_err("usb_tx_urb_with_skb for raw_q %d\n", ret);
			skb_queue_head(&ld->sk_raw_tx_q, skb);

			if (ret == -ENODEV || ret == -ENOENT)
				goto exit;

			pm_runtime_put(&usb_ld->usbdev->dev);
			goto retry_tx_work;
		}

		pm_runtime_put(&usb_ld->usbdev->dev);
	}
	wake_unlock(&pm_data->tx_async_wake);
exit:
	return;

retry_tx_work:
	queue_delayed_work(ld->tx_wq, &ld->tx_delayed_work,
		msecs_to_jiffies(20));
	return;
}
示例#23
0
文件: hw.c 项目: UNwS/rtl8192su
void r92su_hw_queue_service_work(struct r92su *r92su)
{
	queue_delayed_work(system_unbound_wq, &r92su->service_work, 2 * HZ);
}
static int start_ipc(struct link_device *ld, struct io_device *iod)
{
	struct sk_buff *skb;
	char data[1] = {'a'};
	int err;
	struct usb_link_device *usb_ld = to_usb_link_device(ld);
	struct link_pm_data *pm_data = usb_ld->link_pm_data;
	struct device *dev = &usb_ld->usbdev->dev;
	struct if_usb_devdata *pipe_data = &usb_ld->devdata[IF_USB_FMT_EP];

	if (!usb_ld->if_usb_connected) {
		mif_err("HSIC not connected, skip start ipc\n");
		err = -ENODEV;
		goto exit;
	}

retry:
	if (ld->mc->phone_state != STATE_ONLINE) {
		mif_err("MODEM is not online, skip start ipc\n");
		err = -ENODEV;
		goto exit;
	}

	/* check usb runtime pm first */
	if (dev->power.runtime_status != RPM_ACTIVE) {
		if (!pm_data->resume_requested) {
			mif_debug("QW PM\n");
			INIT_COMPLETION(pm_data->active_done);
			queue_delayed_work(pm_data->wq,
					&pm_data->link_pm_work, 0);
		}
		mif_debug("Wait pm\n");
		err = wait_for_completion_timeout(&pm_data->active_done,
							msecs_to_jiffies(500));
		/* timeout or -ERESTARTSYS */
		if (err <= 0)
			goto retry;
	}

	pm_runtime_get_sync(dev);

	mif_err("send 'a'\n");

	skb = alloc_skb(16, GFP_ATOMIC);
	if (unlikely(!skb)) {
		pm_runtime_put(dev);
		return -ENOMEM;
	}
	memcpy(skb_put(skb, 1), data, 1);
	skbpriv(skb)->iod = iod;
	skbpriv(skb)->ld = ld;

	if (!usb_ld->if_usb_connected || !usb_ld->usbdev)
		return -ENODEV;

	usb_mark_last_busy(usb_ld->usbdev);
	err = usb_tx_urb_with_skb(usb_ld->usbdev, skb, pipe_data);
	if (err < 0) {
		mif_err("usb_tx_urb fail\n");
		dev_kfree_skb_any(skb);
	}

	pm_runtime_put(dev);
exit:
	return err;
}
示例#25
0
static int lge_hsd_probe(struct platform_device *pdev)
{
	int ret = 0;
	struct fsa8008_platform_data *pdata = pdev->dev.platform_data;

	struct hsd_info *hi;

	HSD_DBG("lge_hsd_probe");

	hi = kzalloc(sizeof(struct hsd_info), GFP_KERNEL);

	if (NULL == hi) {
		HSD_ERR("Failed to allloate headset per device info\n");
		return -ENOMEM;
	}

	hi->key_code = pdata->key_code;

	platform_set_drvdata(pdev, hi);

	atomic_set(&hi->btn_state, 0);
	atomic_set(&hi->is_3_pole_or_not, 1);

	hi->gpio_detect = pdata->gpio_detect;
	hi->gpio_mic_en = pdata->gpio_mic_en;
	hi->gpio_jpole = pdata->gpio_jpole;
	hi->gpio_key = pdata->gpio_key;
	hi->set_headset_mic_bias = pdata->set_headset_mic_bias;

	hi->latency_for_detection = pdata->latency_for_detection;
#ifdef CONFIG_LGE_AUDIO_FSA8008_MODIFY
	hi->latency_for_key = FSA8008_KEY_PRESS_DLY_MS;
	hi->gpio_key_cnt = 0;
	INIT_DELAYED_WORK(&hi->work_for_insert, insert_headset);
	INIT_DELAYED_WORK(&hi->work_for_remove, remove_headset);
	INIT_DELAYED_WORK(&hi->work_for_key_det_enable, button_enable);
#else
	hi->latency_for_key = 200 /* milli */ * HZ / 1000; /* convert milli to jiffies */
	INIT_DELAYED_WORK(&hi->work, detect_work);
#endif
	mutex_init(&hi->mutex_lock);
	INIT_DELAYED_WORK(&hi->work_for_key_pressed, button_pressed);
	INIT_DELAYED_WORK(&hi->work_for_key_released, button_released);

	/* initialize gpio_detect */
	ret = gpio_request(hi->gpio_detect, "gpio_detect");
	if (ret < 0) {
		HSD_ERR("Failed to configure gpio%d (gpio_detect) gpio_request\n", hi->gpio_detect);
		goto error_01;
	}

	ret = gpio_direction_input(hi->gpio_detect);
	if (ret < 0) {
		HSD_ERR("Failed to configure gpio%d (gpio_detect) gpio_direction_input\n", hi->gpio_detect);
		goto error_02;
	}

	/* initialize gpio_jpole */
	ret = gpio_request(hi->gpio_jpole, "gpio_jpole");
	if (ret < 0) {
		HSD_ERR("Failed to configure gpio%d (gpio_jpole) gpio_request\n", hi->gpio_jpole);
		goto error_02;
	}

	ret = gpio_direction_input(hi->gpio_jpole);
	if (ret < 0) {
		HSD_ERR("Failed to configure gpio%d (gpio_jpole) gpio_direction_input\n", hi->gpio_jpole);
		goto error_03;
	}
	
	/* initialize gpio_key */
	ret = gpio_request(hi->gpio_key, "gpio_key");
	if (ret < 0) {
		HSD_ERR("Failed to configure gpio%d (gpio_key) gpio_request\n", hi->gpio_key);
		goto error_03;
	}

	ret = gpio_direction_input(hi->gpio_key);
	if (ret < 0) {
		HSD_ERR("Failed to configure gpio%d (gpio_key) gpio_direction_input\n", hi->gpio_key);
		goto error_04;
	}

	/* initialize gpio_mic_en */
	ret = gpio_request(hi->gpio_mic_en, "gpio_mic_en");
	if (ret < 0) {
		HSD_ERR("Failed to configure gpio%d (gpio_mic_en) gpio_request\n", hi->gpio_mic_en);
		goto error_04;
	}

	ret = gpio_direction_output(hi->gpio_mic_en, 0);
	if (ret < 0) {
		HSD_ERR("Failed to configure gpio%d (gpio_mic_en) gpio_direction_output\n", hi->gpio_mic_en);
		goto error_05;
	}

	/* initialize irq of gpio_jpole */
	hi->irq_detect = gpio_to_irq(hi->gpio_detect);

	HSD_DBG("hi->irq_detect = %d\n", hi->irq_detect);

	if (hi->irq_detect < 0) {
		HSD_ERR("Failed to get interrupt number\n");
		ret = hi->irq_detect;
		goto error_05;
	}

//LGE_START, MYUNGWON.KIM, When Sleep IRQ Doesn't work
	ret = request_threaded_irq(hi->irq_detect, NULL, gpio_irq_handler,
					IRQF_TRIGGER_RISING|IRQF_TRIGGER_FALLING|IRQF_NO_SUSPEND, pdev->name, hi);
//LGE_END, MYUNGWON.KIM

	if (ret) {
		HSD_ERR("failed to request button irq");
		goto error_05;
	}

	ret = irq_set_irq_wake(hi->irq_detect, 1);
	if (ret < 0) {
		HSD_ERR("Failed to set irq_detect interrupt wake\n");
		goto error_06;
	}

	/* initialize irq of gpio_key */
	hi->irq_key = gpio_to_irq(hi->gpio_key);

	HSD_DBG("hi->irq_key = %d\n", hi->irq_key);

	if (hi->irq_key < 0) {
		HSD_ERR("Failed to get interrupt number\n");
		ret = hi->irq_key;
		goto error_06;
	}

//LGE_START, MYUNGWON.KIM, When Sleep IRQ Doesn't work
	ret = request_threaded_irq(hi->irq_key, NULL, button_irq_handler,
					IRQF_TRIGGER_RISING|IRQF_TRIGGER_FALLING|IRQF_NO_SUSPEND, pdev->name, hi);
//LGE_END, MYUNGWON.KIM

	if (ret) {
		HSD_ERR("failed to request button irq");
		goto error_06;
	}

	disable_irq(hi->irq_key);

	ret = irq_set_irq_wake(hi->irq_key, 1);
	if (ret < 0) {
		HSD_ERR("Failed to set irq_key interrupt wake\n");
		goto error_07;
	}

	/* initialize switch device */
	hi->sdev.name = pdata->switch_name;
	hi->sdev.print_state = lge_hsd_print_state;
	hi->sdev.print_name = lge_hsd_print_name;

	ret = switch_dev_register(&hi->sdev);
	if (ret < 0) {
		HSD_ERR("Failed to register switch device\n");
		goto error_07;
	}

	/* initialize input device */
	hi->input = input_allocate_device();
	if (!hi->input) {
		HSD_ERR("Failed to allocate input device\n");
		ret = -ENOMEM;
		goto error_08;
	}

	hi->input->name = pdata->keypad_name;

	hi->input->id.vendor    = 0x0001;
	hi->input->id.product   = 1;
	hi->input->id.version   = 1;

	/*input_set_capability(hi->input, EV_SW, SW_HEADPHONE_INSERT);*/
	set_bit(EV_SYN, hi->input->evbit);
	set_bit(EV_KEY, hi->input->evbit);
	set_bit(EV_SW, hi->input->evbit);
	set_bit(hi->key_code, hi->input->keybit);
	set_bit(SW_HEADPHONE_INSERT, hi->input->swbit);
	set_bit(SW_MICROPHONE_INSERT, hi->input->swbit);

	ret = input_register_device(hi->input);
	if (ret) {
		HSD_ERR("Failed to register input device\n");
		goto error_09;
	}
#ifdef CONFIG_LGE_AUDIO_FSA8008_MODIFY
	if (gpio_get_value_cansleep(hi->gpio_detect) == EARJACK_INSERTED) {
		queue_delayed_work(local_fsa8008_workqueue, &(hi->work_for_insert), 0); /* to detect in initialization with eacjack insertion */
	}
#else
	if (!gpio_get_value_cansleep(hi->gpio_detect))
#ifdef CONFIG_FSA8008_USE_LOCAL_WORK_QUEUE
		queue_delayed_work(local_fsa8008_workqueue, &(hi->work), 0); /* to detect in initialization with eacjack insertion */
#else
		schedule_delayed_work(&(hi->work), 0); /* to detect in initialization with eacjack insertion */
#endif
#endif

#ifdef AT_TEST_GPKD
	err = device_create_file(&pdev->dev, &dev_attr_hookkeylog);
#endif

	return ret;

error_09:
	input_free_device(hi->input);
error_08:
	switch_dev_unregister(&hi->sdev);

error_07:
	free_irq(hi->irq_key, 0);
error_06:
	free_irq(hi->irq_detect, 0);

error_05:
	gpio_free(hi->gpio_mic_en);
error_04:
	gpio_free(hi->gpio_key);
error_03:
	gpio_free(hi->gpio_jpole);
error_02:
	gpio_free(hi->gpio_detect);

error_01:
	mutex_destroy(&hi->mutex_lock);
	kfree(hi);

	return ret;
}
static void link_pm_runtime_work(struct work_struct *work)
{
	int ret;
	struct link_pm_data *pm_data =
		container_of(work, struct link_pm_data, link_pm_work.work);
	struct device *dev = &pm_data->usb_ld->usbdev->dev;

	if (!pm_data->usb_ld->if_usb_connected || pm_data->dpm_suspending)
		return;

	if (pm_data->usb_ld->ld.com_state == COM_NONE)
		return;

	mif_debug("for dev 0x%p : current %d\n", dev,
					dev->power.runtime_status);

	switch (dev->power.runtime_status) {
	case RPM_ACTIVE:
		pm_data->resume_retry_cnt = 0;
		pm_data->resume_requested = false;
		complete(&pm_data->active_done);

		return;
	case RPM_SUSPENDED:
		if (pm_data->resume_requested)
			break;
		pm_data->resume_requested = true;
		wake_lock(&pm_data->rpm_wake);
		ret = link_pm_slave_wake(pm_data);
		if (ret < 0) {
			mif_err("slave wake fail\n");
			wake_unlock(&pm_data->rpm_wake);
			break;
		}

		if (!pm_data->usb_ld->if_usb_connected) {
			wake_unlock(&pm_data->rpm_wake);
			return;
		}

		ret = pm_runtime_resume(dev);
		if (ret < 0) {
			mif_err("resume error(%d)\n", ret);
			if (!pm_data->usb_ld->if_usb_connected) {
				wake_unlock(&pm_data->rpm_wake);
				return;
			}
			/* force to go runtime idle before retry resume */
			if (dev->power.timer_expires == 0 &&
						!dev->power.request_pending) {
				mif_debug("run time idle\n");
				pm_runtime_idle(dev);
			}
		}
		wake_unlock(&pm_data->rpm_wake);
		break;
	default:
		break;
	}
	pm_data->resume_requested = false;

	/* check until runtime_status goes to active */
	/* attemp 10 times, or re-establish modem-link */
	/* if pm_runtime_resume run properly, rpm status must be in ACTIVE */
	if (dev->power.runtime_status == RPM_ACTIVE) {
		pm_data->resume_retry_cnt = 0;
		complete(&pm_data->active_done);
	} else if (pm_data->resume_retry_cnt++ > 10) {
		mif_err("runtime_status(%d), retry_cnt(%d)\n",
			dev->power.runtime_status, pm_data->resume_retry_cnt);
		link_pm_change_modem_state(pm_data, STATE_CRASH_RESET);
	} else
		queue_delayed_work(pm_data->wq, &pm_data->link_pm_work,
							msecs_to_jiffies(20));
}
示例#27
0
static void mcs6000_work(struct work_struct *work)
{
	int x1=0, y1 = 0;
#ifdef LG_FW_MULTI_TOUCH
	int x2=0, y2 = 0;
	static int pre_x1, pre_x2, pre_y1, pre_y2;
	static unsigned int s_input_type = NON_TOUCHED_STATE;
#endif
	unsigned int input_type;
	unsigned int key_touch;	
	unsigned char read_buf[READ_NUM];

	static int key_pressed = 0;
	static int touch_pressed = 0;

	struct mcs6000_ts_device *dev 
		= container_of(to_delayed_work(work), struct mcs6000_ts_device, work);

	dev->pendown = !gpio_get_value(dev->intr_gpio);

	/* read the registers of MCS6000 IC */
	if ( i2c_smbus_read_i2c_block_data(dev->client, MCS6000_TS_INPUT_INFO, READ_NUM, read_buf) < 0) {
		printk(KERN_ERR "%s touch ic read error\n", __FUNCTION__);
		goto touch_retry;
	}

	input_type = read_buf[0] & 0x0f;
	key_touch = (read_buf[0] & 0xf0) >> 4;

	x1 = y1 =0;
#ifdef LG_FW_MULTI_TOUCH
	x2 = y2 = 0;
#endif
	x1 = (read_buf[1] & 0xf0) << 4;
	y1 = (read_buf[1] & 0x0f) << 8;

	x1 |= read_buf[2];	
	y1 |= read_buf[3];		

#ifdef LG_FW_MULTI_TOUCH
	if(input_type == MULTI_POINT_TOUCH) {
		s_input_type = input_type;
		x2 = (read_buf[5] & 0xf0) << 4;
		y2 = (read_buf[5] & 0x0f) << 8;
		x2 |= read_buf[6];
		y2 |= read_buf[7];
	}
#endif

	if (dev->pendown) { /* touch pressed case */
#ifdef LG_FW_HARDKEY_BLOCK
		if(dev->hardkey_block == 0)
#endif
		if(key_touch && key_pressed != key_touch) {
			if(key_pressed)
				mcs6000_key_event_touch(key_pressed, RELEASED, dev);
			mcs6000_key_event_touch(key_touch, PRESSED, dev);
			key_pressed = key_touch;
		}

		if(input_type) {
			touch_pressed = 1;

#ifdef LG_FW_MULTI_TOUCH
			if(input_type == MULTI_POINT_TOUCH) {
				mcs6000_multi_ts_event_touch(x1, y1, x2, y2, PRESSED, dev);
				pre_x1 = x1;
				pre_y1 = y1;
				pre_x2 = x2;
				pre_y2 = y2;
			}
			else if(input_type == SINGLE_POINT_TOUCH) {
				mcs6000_multi_ts_event_touch(x1, y1, -1, -1, PRESSED, dev);
				s_input_type = SINGLE_POINT_TOUCH;				
			}
#else
			if(input_type == SINGLE_POINT_TOUCH) {
				mcs6000_single_ts_event_touch(x1, y1, PRESSED, dev);
			}
#endif
#ifdef LG_FW_HARDKEY_BLOCK
			dev->hardkey_block = 1;
#endif
		}
	} 
	else { /* touch released case */
		if(key_pressed) {
			mcs6000_key_event_touch(key_pressed, RELEASED, dev);
			key_pressed = 0;
		}

		if(touch_pressed) {
#ifdef LG_FW_MULTI_TOUCH
			if(s_input_type == MULTI_POINT_TOUCH) {
				DMSG("%s: multi touch release...(%d, %d), (%d, %d)\n", __FUNCTION__,pre_x1,pre_y1,pre_x2,pre_y2);
				mcs6000_multi_ts_event_touch(pre_x1, pre_y1, pre_x2, pre_y2, RELEASED, dev);
				s_input_type = NON_TOUCHED_STATE; 
				pre_x1 = -1; pre_y1 = -1; pre_x2 = -1; pre_y2 = -1;
			} else {
				DMSG("%s: single touch release... %d, %d\n", __FUNCTION__, x1, y1);
				mcs6000_multi_ts_event_touch(x1, y1, -1, -1, RELEASED, dev);
			}
#else
			DMSG("%s: single release... %d, %d\n", __FUNCTION__, x1, y1);
			mcs6000_single_ts_event_touch (x1, y1, RELEASED, dev);
			touch_pressed = 0;
#endif
#ifdef LG_FW_HARDKEY_BLOCK
			hrtimer_cancel(&dev->touch_timer);
			hrtimer_start(&dev->touch_timer, ktime_set(0, 800),
			HRTIMER_MODE_REL);
#endif
		}
	}

touch_retry:
	if (dev->pendown) {
		//ret = schedule_delayed_work(&dev->work, msecs_to_jiffies(TS_POLLING_TIME));
		queue_delayed_work(dev->ts_wq, &dev->work,msecs_to_jiffies(TS_POLLING_TIME));
	} else {
		enable_irq(dev->num_irq);
		DMSG("%s: irq enable\n", __FUNCTION__);
	}
}
示例#28
0
static int hdmi_probe(struct platform_device *pdev)
{
	struct s5p_hdmi_platdata *pdata = NULL;
	struct device *dev = &pdev->dev;
	struct resource *res;
	struct i2c_adapter *phy_adapter;
	struct hdmi_device *hdmi_dev = NULL;
	struct hdmi_driver_data *drv_data;
	int ret;

	dev_info(dev, "probe start\n");

	hdmi_dev = devm_kzalloc(&pdev->dev, sizeof(struct hdmi_device), GFP_KERNEL);
	if (!hdmi_dev) {
		dev_err(&pdev->dev, "no memory for hdmi device\n");
		return -ENOMEM;
	}
	hdmi_dev->dev = dev;

	hdmi_dev->pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL);
	if (!hdmi_dev->pdata) {
		dev_err(&pdev->dev, "no memory for state\n");
		return -ENOMEM;
	}

	/* store platform data ptr to mixer context */
	if (dev->of_node) {
		of_property_read_u32(dev->of_node, "ip_ver", &hdmi_dev->pdata->ip_ver);
		pdata = hdmi_dev->pdata;
	} else {
		hdmi_dev->pdata = dev->platform_data;
		pdata = hdmi_dev->pdata;
	}
	dev_info(dev, "HDMI ip version %d\n", pdata->ip_ver);

	/* mapping HDMI registers */
	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
	if (!res) {
		dev_err(dev, "get hdmi memory resource failed.\n");
		return -ENXIO;
	}
	hdmi_dev->regs = devm_request_and_ioremap(&pdev->dev, res);
	if (hdmi_dev->regs == NULL) {
		dev_err(dev, "failed to claim register region for hdmi\n");
		return -ENOENT;
	}

	/* mapping HDMIPHY_APB registers */
	res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
	if (!res) {
		dev_err(dev, "get hdmiphy memory resource failed.\n");
		return -ENXIO;
	}
	hdmi_dev->phy_regs = devm_request_and_ioremap(&pdev->dev, res);
	if (hdmi_dev->phy_regs == NULL) {
		dev_err(dev, "failed to claim register region for hdmiphy\n");
		return -ENOENT;
	}

	/* Internal hpd */
	res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
	if (!res) {
		dev_err(dev, "get internal interrupt resource failed.\n");
		return -ENXIO;
	}
	ret = devm_request_irq(dev, res->start, hdmi_irq_handler,
			0, "hdmi-int", hdmi_dev);
	if (ret) {
		dev_err(dev, "request int interrupt failed.\n");
		return ret;
	} else {
		hdmi_dev->int_irq = res->start;
		disable_irq(hdmi_dev->int_irq);
		dev_info(dev, "success request hdmi-int irq\n");
	}

	/* setting v4l2 name to prevent WARN_ON in v4l2_device_register */
	strlcpy(hdmi_dev->v4l2_dev.name, dev_name(dev),
		sizeof(hdmi_dev->v4l2_dev.name));
	/* passing NULL owner prevents driver from erasing drvdata */
	ret = v4l2_device_register(NULL, &hdmi_dev->v4l2_dev);
	if (ret) {
		dev_err(dev, "could not register v4l2 device.\n");
		goto fail;
	}

	INIT_WORK(&hdmi_dev->hpd_work, hdmi_hpd_work);
	INIT_DELAYED_WORK(&hdmi_dev->hpd_work_ext, hdmi_hpd_work_ext);

	/* setting the clocks */
	ret = hdmi_resources_init(hdmi_dev);
	if (ret)
		goto fail_vdev;

	/* setting the GPIO */
	ret = hdmi_set_gpio(hdmi_dev);
	if (ret) {
		dev_err(dev, "failed to get GPIO\n");
		goto fail_clk;
	}

	/* register the switch device for HPD */
	hdmi_dev->hpd_switch.name = "hdmi";
	ret = switch_dev_register(&hdmi_dev->hpd_switch);
	if (ret) {
		dev_err(dev, "request switch class failed.\n");
		goto fail_gpio;
	}
	dev_info(dev, "success register switch device\n");

	/* External hpd */
	hdmi_dev->ext_irq = gpio_to_irq(hdmi_dev->res.gpio_hpd);
	ret = devm_request_irq(dev, hdmi_dev->ext_irq, hdmi_irq_handler_ext,
			IRQ_TYPE_EDGE_BOTH, "hdmi-ext", hdmi_dev);
	if (ret) {
		dev_err(dev, "request ext interrupt failed.\n");
		goto fail_switch;
	} else {
		dev_info(dev, "success request hdmi-ext irq\n");
	}
	mutex_init(&hdmi_dev->mutex);

	if (soc_is_exynos5250()) {
		drv_data = (struct hdmi_driver_data *)
			platform_get_device_id(pdev)->driver_data;
		dev_info(dev, "hdmiphy i2c bus number = %d\n", drv_data->hdmiphy_bus);

		phy_adapter = i2c_get_adapter(drv_data->hdmiphy_bus);
		if (phy_adapter == NULL) {
			dev_err(dev, "adapter request failed\n");
			ret = -ENXIO;
			goto fail_mutex;
		}

		hdmi_dev->phy_sd = v4l2_i2c_new_subdev_board(&hdmi_dev->v4l2_dev,
				phy_adapter, &hdmiphy_info, NULL);
		/* on failure or not adapter is no longer useful */
		i2c_put_adapter(phy_adapter);
		if (hdmi_dev->phy_sd == NULL) {
			dev_err(dev, "missing subdev for hdmiphy\n");
			ret = -ENODEV;
			goto fail_mutex;
		}
	}

	hdmi_dev->cur_timings =
		hdmi_conf[HDMI_DEFAULT_TIMINGS_IDX].dv_timings;
	/* FIXME: missing fail preset is not supported */
	hdmi_dev->cur_conf = hdmi_conf[HDMI_DEFAULT_TIMINGS_IDX].conf;

	/* default audio configuration : disable audio */
	hdmi_dev->audio_enable = 0;
	hdmi_dev->audio_channel_count = 2;
	hdmi_dev->sample_rate = DEFAULT_SAMPLE_RATE;
	hdmi_dev->color_range = HDMI_RGB709_0_255;
	hdmi_dev->bits_per_sample = DEFAULT_BITS_PER_SAMPLE;
	hdmi_dev->audio_codec = DEFAULT_AUDIO_CODEC;

	/* hdmi audio master clock */
	ret = hdmi_get_audio_master(hdmi_dev);
	if (ret) {
		hdmi_dev->audio_master_clk = 0;
		dev_warn(dev, "failed to get audio master information\n");
	}

	/* default aspect ratio is 16:9 */
	hdmi_dev->aspect = HDMI_ASPECT_RATIO_16_9;

	/* default HDMI streaming is stoped */
	hdmi_dev->streaming = HDMI_STOP;

	/* register hdmi subdev as entity */
	ret = hdmi_register_entity(hdmi_dev);
	if (ret)
		goto fail_mutex;

	hdmi_entity_info_print(hdmi_dev);

	pm_runtime_enable(dev);

	/* initialize hdcp resource */
	ret = hdcp_prepare(hdmi_dev);
	if (ret)
		goto fail_mutex;

	/* work after booting */
	queue_delayed_work(system_nrt_wq, &hdmi_dev->hpd_work_ext,
					msecs_to_jiffies(1500));
	/* TODO : Check the PHY power off is implemented at pm_domains
	 * If not, PHY power off should be applied at here */

	dev_info(dev, "probe sucessful\n");

	hdmi_debugfs_init(hdmi_dev);

	return 0;

fail_mutex:
	mutex_destroy(&hdmi_dev->mutex);

fail_switch:
	switch_dev_unregister(&hdmi_dev->hpd_switch);

fail_gpio:
	gpio_free(hdmi_dev->res.gpio_hpd);
	gpio_free(hdmi_dev->res.gpio_ls);
	gpio_free(hdmi_dev->res.gpio_dcdc);

fail_clk:
	hdmi_resources_cleanup(hdmi_dev);

fail_vdev:
	v4l2_device_unregister(&hdmi_dev->v4l2_dev);

fail:
	dev_err(dev, "probe failed\n");
	return ret;
}
示例#29
0
static ssize_t pm8058_led_blink_store(struct device *dev,
				       struct device_attribute *attr,
				       const char *buf, size_t count)
{
	struct led_classdev *led_cdev;
	struct pm8058_led_data *ldata;
	int id, mode;
	int val;
	int enable = 0;
#ifdef CONFIG_HTC_HEADSET_MISC
	int *pduties;
#endif

/*struct timespec ts1, ts2;*/

	val = -1;
	sscanf(buf, "%u", &val);
	if (val < 0 || val > 255)
		return -EINVAL;

	led_cdev = (struct led_classdev *) dev_get_drvdata(dev);
	ldata = container_of(led_cdev, struct pm8058_led_data, ldev);

	id = bank_to_id(ldata->bank);
	mode = (id == PM_PWM_LED_KPD) ? PM_PWM_CONF_PWM1 :
					PM_PWM_CONF_PWM1 + (ldata->bank - 4);

	if (ldata->flags & PM8058_LED_BLINK_EN)
		pm8058_pwm_config_led(ldata->pwm_led, id, mode,
				      ldata->out_current);

	LED_INFO_LOG("%s: bank %d blink %d\n", __func__, ldata->bank, val);

	enable = (val > 0) ? 1 : 0;
	if (strcmp(ldata->ldev.name, "charming-led") == 0)
		charming_led_enable(enable);

	switch (val) {
	case -1: /* stop flashing */
		pwm_disable(ldata->pwm_led);
		if (ldata->flags & PM8058_LED_BLINK_EN)
			pm8058_pwm_config_led(ldata->pwm_led, id, mode, 0);
		break;
	case 0:
		pwm_disable(ldata->pwm_led);
		if (led_cdev->brightness) {
			pwm_config(ldata->pwm_led, 64000, 64000);
			pwm_enable(ldata->pwm_led);
		} else {
			if (ldata->flags & PM8058_LED_BLINK_EN)
				pm8058_pwm_config_led(ldata->pwm_led, id,
						      mode, 0);
		}
		break;
	case 1:
		pwm_disable(ldata->pwm_led);
		pwm_config(ldata->pwm_led, 64000, 2000000);
		pwm_enable(ldata->pwm_led);
		break;
	case 2:
		cancel_delayed_work_sync(&ldata->led_delayed_work);
		pwm_disable(ldata->pwm_led);
		ldata->duty_time_ms = 64;
		ldata->period_us = 2000000;
		queue_delayed_work(g_led_work_queue, &ldata->led_delayed_work,
				   msecs_to_jiffies(310));
		break;
	case 3:
		cancel_delayed_work_sync(&ldata->led_delayed_work);
		pwm_disable(ldata->pwm_led);
		ldata->duty_time_ms = 64;
		ldata->period_us = 2000000;
		queue_delayed_work(g_led_work_queue, &ldata->led_delayed_work,
				   msecs_to_jiffies(1000));
		break;
	case 4:
		pwm_disable(ldata->pwm_led);
		pwm_config(ldata->pwm_led, 1000000, 2000000);
#if 0
		pwm_conf.pwm_size = 9;
		pwm_conf.clk = PM_PWM_CLK_1KHZ;
		pwm_conf.pre_div = PM_PWM_PREDIVIDE_2;
		pwm_conf.pre_div_exp = 1;
		pwm_conf.pwm_value = 512/2;
		pwm_conf.bypass_lut = 1;
		pwm_configure(ldata->pwm_led, &pwm_conf);
#endif
		pwm_enable(ldata->pwm_led);
		break;
	case 5:
		pwm_disable(ldata->pwm_led);
		pwm_config(ldata->pwm_led, 100000, 200000);
		pwm_enable(ldata->pwm_led);
		break;
#ifdef CONFIG_HTC_HEADSET_MISC
	case 6:
		pm8058_pwm_config_led(ldata->pwm_led, id, mode,
				      ldata->out_current);
		pduties = &duties[ldata->start_index];
		pm8058_pwm_lut_config(ldata->pwm_led, ldata->period_us,
				      pduties, ldata->duty_time_ms,
				      ldata->start_index, ldata->duites_size,
				      0, 0, ldata->lut_flag);
		pm8058_pwm_lut_enable(ldata->pwm_led, 0);
		pm8058_pwm_lut_enable(ldata->pwm_led, 1);
		break;
	case 7:
		pwm_disable(ldata->pwm_led);
		pwm_config(ldata->pwm_led, 64000, 4000000);
		pwm_enable(ldata->pwm_led);
		break;
#endif
	default:
		LED_ERR_LOG(KERN_INFO "%s: bank %d not support blink %d\n", __func__, ldata->bank, val);
		return -EINVAL;
	}
	return count;
}
示例#30
0
static void tegra_auto_hotplug_work_func(struct work_struct *work)
{
	bool up = false;
	unsigned int cpu = nr_cpu_ids;
	unsigned long now = jiffies;
	static unsigned long last_change_time;

	mutex_lock(tegra3_cpu_lock);

	switch (hp_state) {
	case TEGRA_HP_DISABLED:
	case TEGRA_HP_IDLE:
		break;
	case TEGRA_HP_DOWN:
		cpu = tegra_get_slowest_cpu_n();
		if (cpu < nr_cpu_ids) {
			up = false;
		} else if (!is_lp_cluster() && !no_lp &&
			   !pm_qos_request(PM_QOS_MIN_ONLINE_CPUS)) {
			if(!clk_set_parent(cpu_clk, cpu_lp_clk)) {
				hp_stats_update(CONFIG_NR_CPUS, true);
				hp_stats_update(0, false);
				/* catch-up with governor target speed */
				tegra_cpu_set_speed_cap(NULL);
				break;
			}
		}
		queue_delayed_work(
			hotplug_wq, &hotplug_work, down_delay);
		break;
	case TEGRA_HP_UP:
		if (is_lp_cluster() && !no_lp) {
			if(!clk_set_parent(cpu_clk, cpu_g_clk)) {
				hp_stats_update(CONFIG_NR_CPUS, false);
				hp_stats_update(0, true);
				/* catch-up with governor target speed */
				tegra_cpu_set_speed_cap(NULL);
			}
		} else {
			switch (tegra_cpu_speed_balance()) {
			/* cpu speed is up and balanced - one more on-line */
			case TEGRA_CPU_SPEED_BALANCED:
				cpu = cpumask_next_zero(0, cpu_online_mask);
				if (cpu < nr_cpu_ids)
					up = true;
				break;
			/* cpu speed is up, but skewed - remove one core */
			case TEGRA_CPU_SPEED_SKEWED:
				cpu = tegra_get_slowest_cpu_n();
				if (cpu < nr_cpu_ids)
					up = false;
				break;
			/* cpu speed is up, but under-utilized - do nothing */
			case TEGRA_CPU_SPEED_BIASED:
			default:
				break;
			}
		}
		queue_delayed_work(
			hotplug_wq, &hotplug_work, up2gn_delay);
		break;
	default:
		pr_err("%s: invalid tegra hotplug state %d\n",
		       __func__, hp_state);
	}

	if (!up && ((now - last_change_time) < down_delay))
			cpu = nr_cpu_ids;

	if (cpu < nr_cpu_ids) {
		last_change_time = now;
		hp_stats_update(cpu, up);
	}
	mutex_unlock(tegra3_cpu_lock);

	if (cpu < nr_cpu_ids) {
		if (up){
			printk("cpu_up(%u)+\n",cpu);
			cpu_up(cpu);
			printk("cpu_up(%u)-\n",cpu);
		}else{
			printk("cpu_down(%u)+\n",cpu);
			cpu_down(cpu);
			printk("cpu_down(%u)-\n",cpu);
		}
	}
}