Esempio n. 1
0
static void scale3d_clocks(unsigned long percent)
{
    unsigned long hz, curr;

    if (!tegra_is_clk_enabled(scale3d.clk_3d))
        return;

    if (tegra_get_chipid() == TEGRA_CHIPID_TEGRA3)
        if (!tegra_is_clk_enabled(scale3d.clk_3d2))
            return;

    curr = clk_get_rate(scale3d.clk_3d);
    hz = percent * (curr / 100);

    if (!(hz >= scale3d.max_rate_3d && curr == scale3d.max_rate_3d)) {
        if (tegra_get_chipid() == TEGRA_CHIPID_TEGRA3)
            clk_set_rate(scale3d.clk_3d2, 0);
        clk_set_rate(scale3d.clk_3d, hz);

        if (scale3d.p_scale_emc) {
            long after = (long) clk_get_rate(scale3d.clk_3d);
            hz = after * scale3d.emc_slope + scale3d.emc_offset;
            if (scale3d.p_emc_dip)
                hz -=
                    (scale3d.emc_dip_slope *
                     POW2(after / 1000 - scale3d.emc_xmid) +
                     scale3d.emc_dip_offset);
            clk_set_rate(scale3d.clk_3d_emc, hz);
        }
    }
}
/* use the larger of dc->emc_clk_rate or dc->new_emc_clk_rate, and copies
 * dc->new_emc_clk_rate into dc->emc_clk_rate.
 * calling this function both before and after a flip is sufficient to select
 * the best possible frequency and latency allowance.
 * set use_new to true to force dc->new_emc_clk_rate programming.
 */
void tegra_dc_program_bandwidth(struct tegra_dc *dc, bool use_new)
{
	unsigned i;

	if (use_new || dc->emc_clk_rate != dc->new_emc_clk_rate) {
		/* going from 0 to non-zero */
		if (!dc->emc_clk_rate && !tegra_is_clk_enabled(dc->emc_clk))
			clk_prepare_enable(dc->emc_clk);

		clk_set_rate(dc->emc_clk,
			max(dc->emc_clk_rate, dc->new_emc_clk_rate));
		dc->emc_clk_rate = dc->new_emc_clk_rate;

		/* going from non-zero to 0 */
		if (!dc->new_emc_clk_rate && tegra_is_clk_enabled(dc->emc_clk))
			clk_disable_unprepare(dc->emc_clk);
	}

	for (i = 0; i < DC_N_WINDOWS; i++) {
		struct tegra_dc_win *w = &dc->windows[i];

		if ((use_new || w->bandwidth != w->new_bandwidth) &&
			w->new_bandwidth != 0)
			tegra_dc_set_latency_allowance(dc, w);
		trace_program_bandwidth(dc);
		w->bandwidth = w->new_bandwidth;
	}
}
Esempio n. 3
0
/* use the larger of dc->emc_clk_rate or dc->new_emc_clk_rate, and copies
 * dc->new_emc_clk_rate into dc->emc_clk_rate.
 * calling this function both before and after a flip is sufficient to select
 * the best possible frequency and latency allowance.
 * set use_new to true to force dc->new_emc_clk_rate programming.
 */
void tegra_dc_program_bandwidth(struct tegra_dc *dc, bool use_new)
{
	unsigned i;
//                                                                              
//	int temp_emc_clk;

	if (use_new || dc->emc_clk_rate != dc->new_emc_clk_rate) {
		/* going from 0 to non-zero */
		if (!dc->emc_clk_rate && !tegra_is_clk_enabled(dc->emc_clk))
			clk_enable(dc->emc_clk);

//                                                                                                             
//		clk_set_rate(dc->emc_clk,
//		max(dc->emc_clk_rate, dc->new_emc_clk_rate));
//                               

//                                   
		clk_set_rate(dc->emc_clk,
			max(dc->emc_clk_rate, dc->new_emc_clk_rate));
/*                                     
                                                          
                                                             
                                                                       
                                          
                                 
*/
		dc->emc_clk_rate = dc->new_emc_clk_rate;

//                                                           
//                                      
//                            
//		dc->emc_clk_rate = (dc->emc_clk_rate > 204000000) ? dc->emc_clk_rate : 204000000;
//#endif		
//                                      
//                               

		/* going from non-zero to 0 */
		if (!dc->new_emc_clk_rate && tegra_is_clk_enabled(dc->emc_clk))
			clk_disable(dc->emc_clk);
	}
/*                                     
                                                          
                                                  
                                        
  
                                  
*/

	for (i = 0; i < DC_N_WINDOWS; i++) {
		struct tegra_dc_win *w = &dc->windows[i];

		if ((use_new || w->bandwidth != w->new_bandwidth) &&
			w->new_bandwidth != 0)
			tegra_dc_set_latency_allowance(dc, w);
		trace_program_bandwidth(dc);
		w->bandwidth = w->new_bandwidth;
	}
}
Esempio n. 4
0
static void scale3d_clocks(unsigned long percent)
{
	unsigned long hz, curr;
	int i = 0;
	ktime_t t;

	if (!tegra_is_clk_enabled(scale3d.clk_3d))
		return;

	if (tegra_get_chipid() == TEGRA_CHIPID_TEGRA3)
		if (!tegra_is_clk_enabled(scale3d.clk_3d2))
			return;

	curr = clk_get_rate(scale3d.clk_3d);
	hz = percent * (curr / 100);

	if (!(hz >= scale3d.max_rate_3d && curr == scale3d.max_rate_3d)) {
		if (tegra_get_chipid() == TEGRA_CHIPID_TEGRA3)
			clk_set_rate(scale3d.clk_3d2, 0);

		if (is_tegra_camera_on())
			clk_set_rate(scale3d.clk_3d, CAMERA_3D_CLK);
		else
			clk_set_rate(scale3d.clk_3d, hz);

		if (scale3d.p_scale_emc) {
			long after = (long) clk_get_rate(scale3d.clk_3d);
			hz = after * scale3d.emc_slope + scale3d.emc_offset;
			if (scale3d.p_emc_dip)
				hz -=
					(scale3d.emc_dip_slope *
					POW2(after / 1000 - scale3d.emc_xmid) +
					scale3d.emc_dip_offset);
			if (is_tegra_camera_on())
				clk_set_rate(scale3d.clk_3d_emc, CAMERA_3D_EMC_CLK);
			else
				clk_set_rate(scale3d.clk_3d_emc, hz);
		}
	}
	t = ktime_get();

	hz = clk_get_rate(scale3d.clk_3d);

	if (hz != curr)
	{
		gpu_loading[curr_idx].total_time +=
			ktime_us_delta(t, gpu_loading[curr_idx].last_start);

		for (i=0 ; i<FREQ_LEVEL ; i++) {
			if (gpu_loading[i].freq == hz) {
				curr_idx = i;
				break;
			}
		}

		gpu_loading[curr_idx].last_start = t;
	}
}
/* to save power, call when display memory clients would be idle */
void tegra_dc_clear_bandwidth(struct tegra_dc *dc)
{
	trace_clear_bandwidth(dc);
	if (tegra_is_clk_enabled(dc->emc_clk))
		clk_disable_unprepare(dc->emc_clk);
	dc->emc_clk_rate = 0;
}
Esempio n. 6
0
void tegra_dc_clk_disable(struct tegra_dc *dc)
{
	if (tegra_is_clk_enabled(dc->clk)) {
		clk_disable(dc->clk);
		tegra_dvfs_set_rate(dc->clk, 0);
	}
}
Esempio n. 7
0
void tegra_dc_clk_enable(struct tegra_dc *dc)
{
	if (!tegra_is_clk_enabled(dc->clk)) {
		clk_enable(dc->clk);
		tegra_dvfs_set_rate(dc->clk, dc->mode.pclk);
	}
}
/* to save power, call when display memory clients would be idle */
void tegra_dc_clear_bandwidth(struct tegra_dc *dc)
{
	trace_printk("%s:%s rate=%d\n", dc->ndev->name, __func__,
		dc->emc_clk_rate);
	if (tegra_is_clk_enabled(dc->emc_clk))
		clk_disable(dc->emc_clk);
	dc->emc_clk_rate = 0;
}
Esempio n. 9
0
static void do_scale(int diff)
{
	unsigned long hz, curr;

	if (!tegra_is_clk_enabled(scale3d.clk_3d))
		return;

	if (tegra_get_chipid() == TEGRA_CHIPID_TEGRA3)
		if (!tegra_is_clk_enabled(scale3d.clk_3d2))
			return;

	curr = clk_get_rate(scale3d.clk_3d);
	hz = curr + diff;

	if (hz < scale3d.min_rate_3d)
		hz = scale3d.min_rate_3d;

	if (hz > scale3d.max_rate_3d)
		hz = scale3d.max_rate_3d;

	if (hz == curr) return;

	if (tegra_get_chipid() == TEGRA_CHIPID_TEGRA3)
		clk_set_rate(scale3d.clk_3d2, 0);

	if (is_tegra_camera_on())
		clk_set_rate(scale3d.clk_3d, CAMERA_3D_CLK);
	else
		clk_set_rate(scale3d.clk_3d, hz);

	if (scale3d.p_scale_emc) {
		long after = (long) clk_get_rate(scale3d.clk_3d);
		hz = after * scale3d.emc_slope + scale3d.emc_offset;
		if (scale3d.p_emc_dip)
			hz -=
				(scale3d.emc_dip_slope *
				POW2(after / 1000 - scale3d.emc_xmid) +
				scale3d.emc_dip_offset);
		if (is_tegra_camera_on())
			clk_set_rate(scale3d.clk_3d_emc, CAMERA_3D_EMC_CLK);
		else
			clk_set_rate(scale3d.clk_3d_emc, hz);
	}
}
static int nvhost_scale3d_target(struct device *d, unsigned long *freq,
				u32 flags)
{
	long hz;
	long after;

	/* Inform that the clock is disabled */
	if (!tegra_is_clk_enabled(power_profile.clk_3d)) {
		*freq = 0;
		return 0;
	}

	/* Limit the frequency */
	if (*freq < power_profile.min_rate_3d)
		*freq = power_profile.min_rate_3d;
	else if (*freq > power_profile.max_rate_3d)
		*freq = power_profile.max_rate_3d;

	/* Check if we're already running at the desired speed */
	if (*freq == clk_get_rate(power_profile.clk_3d))
		return 0;

	/* Set GPU clockrate */
	if (tegra_get_chipid() == TEGRA_CHIPID_TEGRA3)
		nvhost_module_set_devfreq_rate(power_profile.dev,
					clk_to_idx(power_profile.clk_3d2), 0);
	nvhost_module_set_devfreq_rate(power_profile.dev,
				clk_to_idx(power_profile.clk_3d), *freq);

	/* Set EMC clockrate */
	after = (long) clk_get_rate(power_profile.clk_3d);
	after = INT_TO_FX(HZ_TO_MHZ(after));
	hz = FXMUL(after, power_profile.emc_slope) +
		power_profile.emc_offset;

	hz -= FXMUL(power_profile.emc_dip_slope,
		FXMUL(after - power_profile.emc_xmid,
			after - power_profile.emc_xmid)) +
		power_profile.emc_dip_offset;

	hz = MHZ_TO_HZ(FX_TO_INT(hz + FX_HALF)); /* round to nearest */
	hz = (hz < 0) ? 0 : hz;

	nvhost_module_set_devfreq_rate(power_profile.dev,
			clk_to_idx(power_profile.clk_3d_emc), hz);

	/* Get the new clockrate */
	*freq = clk_get_rate(power_profile.clk_3d);

	return 0;
}
Esempio n. 11
0
static void scale3d_idle_handler(struct work_struct *work)
{
    int notify_idle = 0;

    mutex_lock(&scale3d.lock);

    if (scale3d.enable && scale3d.is_idle &&
            tegra_is_clk_enabled(scale3d.clk_3d)) {
        unsigned long curr = clk_get_rate(scale3d.clk_3d);
        if (curr > scale3d.min_rate_3d)
            notify_idle = 1;
    }

    mutex_unlock(&scale3d.lock);

    if (notify_idle)
        nvhost_scale3d_notify_idle(NULL);
}
Esempio n. 12
0
void tegra_asoc_utils_fini(struct tegra_asoc_utils_data *data)
{
	if (!IS_ERR(data->clk_out1))
		clk_put(data->clk_out1);

	clk_put(data->clk_cdev1);
	/* Just to make sure that clk_cdev1 should turn off in case if it is
	 * switched on by some codec whose hw switch is not registered.*/
	if (tegra_is_clk_enabled(data->clk_cdev1))
		clk_disable(data->clk_cdev1);

	if (!IS_ERR(data->clk_pll_a_out0))
		clk_put(data->clk_pll_a_out0);

	if (!IS_ERR(data->clk_pll_a))
		clk_put(data->clk_pll_a);

	if (!IS_ERR(data->clk_pll_p_out1))
		clk_put(data->clk_pll_p_out1);
}
Esempio n. 13
0
static void handle_recheck_edid_l(struct tegra_dc_hdmi_data *hdmi)
{
	int match, tgt_state, timeout;

	tgt_state = HDMI_STATE_RESET;
	timeout = 0;

	if (hdmi_recheck_edid(hdmi, &match)) {
		/* Failed to read EDID.  If we still have retry attempts left,
		 * schedule another attempt.  Otherwise give up and reset;
		 */
		work_state.edid_reads++;
		if (work_state.edid_reads >= MAX_EDID_READ_ATTEMPTS) {
			pr_info("Failed to read EDID after %d times. Giving up.\n",
				work_state.edid_reads);
		} else {
			tgt_state = HDMI_STATE_DONE_RECHECK_EDID;
			timeout = CHECK_EDID_DELAY_MS;
		}
	} else {
		/* Successful read!  If the EDID is unchanged, just go back to
		 * the DONE_ENABLED state and do nothing.  If something changed,
		 * just reset the whole system.
		 */
		if (match) {
			pr_info("No EDID change after HPD bounce, taking no action.\n");
			tgt_state = HDMI_STATE_DONE_ENABLED;
			if (tegra_is_clk_enabled(hdmi->dc->clk)) {
				tegra_nvhdcp_set_plug(hdmi->nvhdcp, 0);
				tegra_nvhdcp_set_plug(hdmi->nvhdcp, 1);
			} else {
				pr_info("dc powergated, skipping hdcp reset\n");
			}
			timeout = -1;
		} else {
			pr_info("EDID change after HPD bounce, resetting\n");
		}
	}

	hdmi_state_machine_set_state_l(tgt_state, timeout);
}
Esempio n. 14
0
static int nvhost_scale_target(struct device *dev, unsigned long *freq,
			       u32 flags)
{
	struct nvhost_device_data *pdata = dev_get_drvdata(dev);
	struct nvhost_device_profile *profile = pdata->power_profile;

	if (!tegra_is_clk_enabled(profile->clk)) {
		*freq = profile->devfreq_profile.freq_table[0];
		return 0;
	}

	*freq = clk_round_rate(clk_get_parent(profile->clk), *freq);
	if (clk_get_rate(profile->clk) == *freq)
		return 0;

	nvhost_module_set_devfreq_rate(profile->pdev, 0, *freq);
	if (pdata->scaling_post_cb)
		pdata->scaling_post_cb(profile, *freq);

	*freq = clk_get_rate(profile->clk);

	return 0;
}
Esempio n. 15
0
int is_partition_clk_disabled(struct powergate_partition_info *pg_info)
{
	u32 idx;
	struct clk *clk;
	struct partition_clk_info *clk_info;
	int ret = 0;

	for (idx = 0; idx < MAX_CLK_EN_NUM; idx++) {
		clk_info = &pg_info->clk_info[idx];
		clk = clk_info->clk_ptr;

		if (!clk)
			break;

		if (clk_info->clk_type != RST_ONLY) {
			if (tegra_is_clk_enabled(clk)) {
				ret = -1;
				break;
			}
		}
	}

	return ret;
}
Esempio n. 16
0
static void handle_check_edid_l(struct tegra_dc_hdmi_data *hdmi)
{
	struct fb_monspecs specs;
#ifdef CONFIG_SWITCH
	int state;
#endif

	memset(&specs, 0, sizeof(specs));
#ifdef CONFIG_FRAMEBUFFER_CONSOLE
	/* Set default videomode on dc before enabling it*/
	tegra_dc_set_default_videomode(hdmi->dc);
#endif

	if (!tegra_dc_hpd(work_state.hdmi->dc)) {
		/* hpd dropped - stop EDID read */
		pr_info("hpd == 0, aborting EDID read\n");
		goto end_disabled;
	}

	if (tegra_edid_get_monspecs(hdmi->edid, &specs)) {
		/* Failed to read EDID.  If we still have retry attempts left,
		 * schedule another attempt.  Otherwise give up and just go to
		 * the disabled state.
		 */
		work_state.edid_reads++;
		if (work_state.edid_reads >= MAX_EDID_READ_ATTEMPTS) {
			pr_info("Failed to read EDID after %d times. Giving up.\n",
				work_state.edid_reads);
			goto end_disabled;
		} else {
			hdmi_state_machine_set_state_l(HDMI_STATE_CHECK_EDID,
						       CHECK_EDID_DELAY_MS);
		}

		return;
	}

	if (tegra_edid_get_eld(hdmi->edid, &hdmi->eld) < 0) {
		pr_err("error populating eld\n");
		goto end_disabled;
	}
	hdmi->eld_retrieved = true;

	pr_info("panel size %d by %d\n", specs.max_x, specs.max_y);

	/* monitors like to lie about these but they are still useful for
	 * detecting aspect ratios
	 */
	hdmi->dc->out->h_size = specs.max_x * 1000;
	hdmi->dc->out->v_size = specs.max_y * 1000;

	hdmi->dvi = !(specs.misc & FB_MISC_HDMI);

#ifdef CONFIG_ADF_TEGRA
	tegra_adf_process_hotplug_connected(hdmi->dc->adf, &specs);
#endif
#ifdef CONFIG_TEGRA_DC_EXTENSIONS
	tegra_fb_update_monspecs(hdmi->dc->fb, &specs,
		tegra_dc_hdmi_mode_filter);
#endif
#ifdef CONFIG_SWITCH
	state = tegra_edid_audio_supported(hdmi->edid) ? 1 : 0;
	switch_set_state(&hdmi->audio_switch, state);
	pr_info("%s: audio_switch %d\n", __func__, state);
	switch_set_state(&hdmi->hpd_switch, 1);
	pr_info("Display connected, hpd_switch 1\n");
#endif
	hdmi->dc->connected = true;

#ifdef CONFIG_TEGRA_DC_EXTENSIONS
	tegra_dc_ext_process_hotplug(hdmi->dc->ndev->id);
#endif

	if (unlikely(tegra_is_clk_enabled(hdmi->clk))) {
		/* the only time this should happen is on boot, where the
		 * sequence is that hdmi is enabled before EDID is read.
		 * hdmi_enable() doesn't have EDID information yet so can't
		 * setup audio and infoframes, so we have to do so here.
		 */
		pr_info("%s: setting audio and infoframes\n", __func__);
		tegra_dc_io_start(hdmi->dc);
		tegra_dc_hdmi_setup_audio_and_infoframes(hdmi->dc);
		tegra_dc_io_end(hdmi->dc);
	}

	hdmi_state_machine_set_state_l(HDMI_STATE_DONE_ENABLED, -1);

	return;

end_disabled:
	hdmi->eld_retrieved = false;
	hdmi_disable_l(hdmi);
	hdmi_state_machine_set_state_l(HDMI_STATE_DONE_DISABLED, -1);
}
Esempio n. 17
0
int tegra_asoc_utils_set_rate(struct tegra_asoc_utils_data *data, int srate,
			      int mclk)
{
	int new_baseclock;
	bool clk_change;
	int err;
	bool reenable_clock;

	switch (srate) {
	case 11025:
	case 22050:
	case 44100:
	case 88200:
		if (data->soc == TEGRA_ASOC_UTILS_SOC_TEGRA20)
			new_baseclock = 56448000;
		else if (data->soc == TEGRA_ASOC_UTILS_SOC_TEGRA30)
			new_baseclock = 564480000;
		else
			new_baseclock = 282240000;
		break;
	case 8000:
	case 16000:
	case 32000:
	case 48000:
	case 64000:
	case 96000:
		if (data->soc == TEGRA_ASOC_UTILS_SOC_TEGRA20)
			new_baseclock = 73728000;
		else if (data->soc == TEGRA_ASOC_UTILS_SOC_TEGRA30)
			new_baseclock = 552960000;
		else
			new_baseclock = 368640000;
		break;
	default:
		return -EINVAL;
	}

	clk_change = ((new_baseclock != data->set_baseclock) ||
			(mclk != data->set_mclk));
	if (!clk_change)
		return 0;

	/* Don't change rate if already one dai-link is using it */
	if (data->lock_count)
		return -EINVAL;

	data->set_baseclock = 0;
	data->set_mclk = 0;

	reenable_clock = false;
	if(tegra_is_clk_enabled(data->clk_pll_a)) {
		clk_disable_unprepare(data->clk_pll_a);
		reenable_clock = true;
	}

	err = clk_set_rate(data->clk_pll_a, new_baseclock);
	if (err) {
		dev_err(data->dev, "Can't set pll_a rate: %d\n", err);
		return err;
	}
	if(reenable_clock)
		clk_prepare_enable(data->clk_pll_a);

	reenable_clock = false;
	if(tegra_is_clk_enabled(data->clk_pll_a_out0)) {
		clk_disable_unprepare(data->clk_pll_a_out0);
		reenable_clock = true;
	}
	err = clk_set_rate(data->clk_pll_a_out0, mclk);
	if (err) {
		dev_err(data->dev, "Can't set clk_pll_a_out0 rate: %d\n", err);
		return err;
	}
	if(reenable_clock)
		clk_prepare_enable(data->clk_pll_a_out0);

	data->set_baseclock = new_baseclock;
	data->set_mclk = mclk;

	return 0;
}