コード例 #1
0
ファイル: dss.c プロジェクト: 3sOx/asuswrt-merlin
void dss_dump_clocks(struct seq_file *s)
{
	unsigned long dpll4_ck_rate;
	unsigned long dpll4_m4_ck_rate;

	dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK1);

	dpll4_ck_rate = clk_get_rate(clk_get_parent(dss.dpll4_m4_ck));
	dpll4_m4_ck_rate = clk_get_rate(dss.dpll4_m4_ck);

	seq_printf(s, "- DSS -\n");

	seq_printf(s, "dpll4_ck %lu\n", dpll4_ck_rate);

	if (cpu_is_omap3630())
		seq_printf(s, "dss1_alwon_fclk = %lu / %lu  = %lu\n",
			dpll4_ck_rate,
			dpll4_ck_rate / dpll4_m4_ck_rate,
			dss_clk_get_rate(DSS_CLK_FCK1));
	else
		seq_printf(s, "dss1_alwon_fclk = %lu / %lu * 2 = %lu\n",
			dpll4_ck_rate,
			dpll4_ck_rate / dpll4_m4_ck_rate,
			dss_clk_get_rate(DSS_CLK_FCK1));

	dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK1);
}
コード例 #2
0
int dpi_check_timings(struct omap_dss_device *dssdev,
			struct omap_video_timings *timings)
{
	struct dispc_clock_info dispc_cinfo;
	bool is_tft;

	if (!dispc_lcd_timings_ok(timings))
		return -EINVAL;

	if (timings->pixel_clock == 0)
		return -EINVAL;

	is_tft = (dssdev->panel.config & OMAP_DSS_LCD_TFT) != 0;

#ifdef CONFIG_OMAP2_DSS_USE_DSI_PLL
	{
		struct dsi_clock_info dsi_cinfo;
		int r = 0;

		if (cpu_is_omap44xx()) {
			dsi_cinfo.regn = 17;
			dsi_cinfo.regm = 150;
			dsi_cinfo.regm_dispc = 4;
			dsi_cinfo.regm_dsi = 4;
			dsi_cinfo.use_dss2_fck = true;
			r = dsi_calc_clock_rates(&dsi_cinfo);
			if (r)
				return r;
			dispc_find_clk_divs(is_tft, timings->pixel_clock * 1000,
				dsi_cinfo.dsi_pll_dispc_fclk, &dispc_cinfo);
		} else {
			r = dsi_pll_calc_clock_div_pck(dssdev->channel ==
					OMAP_DSS_CHANNEL_LCD ? DSI1 : DSI2,
					is_tft, timings->pixel_clock * 1000,
					&dsi_cinfo, &dispc_cinfo);
			if (r)
				return r;
		}
	}
#else /* #ifdef CONFIG_OMAP2_DSS_USE_DSI_PLL */
	if (cpu_is_omap44xx())
		dispc_find_clk_divs(is_tft, timings->pixel_clock * 1000,
			dss_clk_get_rate(DSS_CLK_FCK1), &dispc_cinfo);
	else {
		struct dss_clock_info dss_cinfo;
		int r = 0;

		r = dss_calc_clock_div(is_tft, timings->pixel_clock * 1000,
				&dss_cinfo, &dispc_cinfo);
		if (r)
			return r;
	}
#endif /* CONFIG_OMAP2_DSS_USE_DSI_PLL */

	timings->pixel_clock = dispc_cinfo.pck / 1000;

	return 0;
}
コード例 #3
0
ファイル: dss.c プロジェクト: mfleming/linux-2.6
int dss_get_clock_div(struct dss_clock_info *cinfo)
{
	cinfo->fck = dss_clk_get_rate(DSS_CLK_FCK1);

	if (cpu_is_omap34xx()) {
		unsigned long prate;
		prate = clk_get_rate(clk_get_parent(dss.dpll4_m4_ck));
		cinfo->fck_div = prate / (cinfo->fck / 2);
	} else {
		cinfo->fck_div = 0;
	}

	return 0;
}
コード例 #4
0
ファイル: rfbi.c プロジェクト: AdiPat/android_kernel_tegra_n1
unsigned long rfbi_get_max_tx_rate(void)
{
	unsigned long   l4_rate, dss1_rate;
	int             min_l4_ticks = 0;
	int             i;

	/* According to TI this can't be calculated so make the
	 * adjustments for a couple of known frequencies and warn for
	 * others.
	 */
	static const struct {
		unsigned long l4_clk;           /* HZ */
		unsigned long dss1_clk;         /* HZ */
		unsigned long min_l4_ticks;
	} ftab[] = {
		{ 55,   132,    7, },           /* 7.86 MPix/s */
		{ 110,  110,    12, },          /* 9.16 MPix/s */
		{ 110,  132,    10, },          /* 11   Mpix/s */
		{ 120,  120,    10, },          /* 12   Mpix/s */
		{ 133,  133,    10, },          /* 13.3 Mpix/s */
	};

	l4_rate = rfbi.l4_khz / 1000;
	dss1_rate = dss_clk_get_rate(DSS_CLK_FCK1) / 1000000;

	for (i = 0; i < ARRAY_SIZE(ftab); i++) {
		/* Use a window instead of an exact match, to account
		 * for different DPLL multiplier / divider pairs.
		 */
		if (abs(ftab[i].l4_clk - l4_rate) < 3 &&
		    abs(ftab[i].dss1_clk - dss1_rate) < 3) {
			min_l4_ticks = ftab[i].min_l4_ticks;
			break;
		}
	}
	if (i == ARRAY_SIZE(ftab)) {
		/* Can't be sure, return anyway the maximum not
		 * rate-limited. This might cause a problem only for the
		 * tearing synchronisation.
		 */
		DSSERR("can't determine maximum RFBI transfer rate\n");
		return rfbi.l4_khz * 1000;
	}
	return rfbi.l4_khz * 1000 / min_l4_ticks;
}
コード例 #5
0
int rfbi_init(void)
{
	u32 rev;
	u32 l;

	spin_lock_init(&rfbi.cmd_lock);
	rfbi.cmd_fifo = kfifo_alloc(RFBI_CMD_FIFO_LEN_BYTES, GFP_KERNEL,
				    &rfbi.cmd_lock);
	if (IS_ERR(rfbi.cmd_fifo))
		return -ENOMEM;

	init_completion(&rfbi.cmd_done);
	init_completion(&rfbi.update_done);
	atomic_set(&rfbi.cmd_fifo_full, 0);
	atomic_set(&rfbi.cmd_pending, 0);

	rfbi.base = ioremap(RFBI_BASE, SZ_256);
	if (!rfbi.base) {
		DSSERR("can't ioremap RFBI\n");
		return -ENOMEM;
	}

	rfbi_enable_clocks(1);

	msleep(10);

	rfbi.l4_khz = dss_clk_get_rate(DSS_CLK_ICK) / 1000;

	/* Enable autoidle and smart-idle */
	l = rfbi_read_reg(RFBI_SYSCONFIG);
	l |= (1 << 0) | (2 << 3);
	rfbi_write_reg(RFBI_SYSCONFIG, l);

	rev = rfbi_read_reg(RFBI_REVISION);
	printk(KERN_INFO "OMAP RFBI rev %d.%d\n",
	       FLD_GET(rev, 7, 4), FLD_GET(rev, 3, 0));

	rfbi_enable_clocks(0);

	return 0;
}
コード例 #6
0
/*
 * linux/drivers/video/omap2/dss/dpi.c
 *
 * Copyright (C) 2009 Nokia Corporation
 * Author: Tomi Valkeinen <*****@*****.**>
 *
 * Some code and ideas taken from drivers/video/omap/ driver
 * by Imre Deak.
 *
 * This program is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 as published by
 * the Free Software Foundation.
 *
 * This program is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
 * more details.
 *
 * You should have received a copy of the GNU General Public License along with
 * this program.  If not, see <http://www.gnu.org/licenses/>.
 */

#define DSS_SUBSYS_NAME "DPI"

#include <linux/kernel.h>
#include <linux/clk.h>
#include <linux/delay.h>
#include <linux/err.h>
#include <linux/errno.h>
#include <linux/platform_device.h>
#include <linux/regulator/consumer.h>

#include <plat/display.h>
#include <plat/cpu.h>
#include <plat/omap-pm.h>

#include "dss.h"

static struct {
	struct regulator *vdds_dsi_reg;
} dpi;

#ifdef CONFIG_OMAP2_DSS_USE_DSI_PLL
static int dpi_set_dsi_clk(enum omap_channel channel, bool is_tft,
		unsigned long pck_req, unsigned long *pck)
{
	struct dsi_clock_info dsi_cinfo;
	struct dispc_clock_info dispc_cinfo;
	int r;
	enum omap_dsi_index ix;

	DSSDBG("DPI clk source is DSI PLL\n");

	ix = (channel == OMAP_DSS_CHANNEL_LCD) ? DSI1 : DSI2;

	if (!cpu_is_omap44xx()) {
		r = dsi_pll_calc_clock_div_pck(ix, is_tft,
			pck_req, &dsi_cinfo, &dispc_cinfo);
		if (r)
			return r;
	} else {
		dsi_cinfo.regn = 16;
		dsi_cinfo.regm = 115;
		dsi_cinfo.regm_dispc = 3;
		dsi_cinfo.regm_dsi = 3;
		dsi_cinfo.use_dss2_fck = true;
		r = dsi_calc_clock_rates(channel, &dsi_cinfo);

		DSSDBG("dpi_set_dsi_clk: dsi_calc_clock_rates=%d\n", r);

		if (r)
			return r;
		dispc_find_clk_divs(is_tft, pck_req,
			dsi_cinfo.dsi_pll_dispc_fclk, &dispc_cinfo);
	}

	r = dsi_pll_set_clock_div(ix, &dsi_cinfo);

	DSSDBG("dpi_set_dsi_clk: dsi_pll_set_clock_div=%d\n", r);
	if (r)
		return r;

	if (cpu_is_omap44xx()){
		dss_select_dispc_clk_source(ix, (ix == DSI1) ?
			DSS_SRC_PLL1_CLK1 : DSS_SRC_PLL2_CLK1);
		dss_select_lcd_clk_source(ix, (ix == DSI1) ?
			DSS_SRC_PLL1_CLK1 : DSS_SRC_PLL2_CLK1);
	}else{
		dss_select_dispc_clk_source(ix, DSS_SRC_DSI1_PLL_FCLK);
        }

	dispc_set_clock_div(channel, &dispc_cinfo);

	*pck = dispc_cinfo.pck;

	return 0;
}
#else /* #ifdef CONFIG_OMAP2_DSS_USE_DSI_PLL */
static int dpi_set_dispc_clk(enum omap_channel channel,
		bool is_tft, unsigned long pck_req, unsigned long *pck)
{
	struct dispc_clock_info dispc_cinfo;
	enum omap_dsi_index ix;

	DSSDBG("DPI clk source is DISPC\n");

	ix = (channel == OMAP_DSS_CHANNEL_LCD) ? DSI1 : DSI2;

	if (cpu_is_omap44xx())
		dispc_find_clk_divs(is_tft, pck_req,
			dss_clk_get_rate(DSS_CLK_FCK1), &dispc_cinfo);
	else {
		struct dss_clock_info dss_cinfo;
		int r;

		r = dss_calc_clock_div(is_tft, pck_req,
				&dss_cinfo, &dispc_cinfo);
		if (r)
			return r;

		r = dss_set_clock_div(&dss_cinfo);
		if (r)
			return r;
	}

	dss_select_dispc_clk_source(ix, DSS_SRC_DSS1_ALWON_FCLK);
	if (cpu_is_omap44xx())
		dss_select_lcd_clk_source(ix, DSS_SRC_DSS1_ALWON_FCLK);

	dispc_set_clock_div(channel, &dispc_cinfo);

	*pck = dispc_cinfo.pck;

	return 0;
}
コード例 #7
0
int dss_calc_clock_div(bool is_tft, unsigned long req_pck,
		struct dss_clock_info *dss_cinfo,
		struct dispc_clock_info *dispc_cinfo)
{
	unsigned long prate;
	struct dss_clock_info best_dss;
	struct dispc_clock_info best_dispc;

	unsigned long fck;

	u16 fck_div;

	int match = 0;
	int min_fck_per_pck;

	prate = dss_get_dpll4_rate();

	fck = dss_clk_get_rate(DSS_CLK_FCK1);
	if (req_pck == dss.cache_req_pck &&
			((cpu_is_omap34xx() && prate == dss.cache_prate) ||
			 dss.cache_dss_cinfo.fck == fck)) {
		DSSDBG("dispc clock info found from cache.\n");
		*dss_cinfo = dss.cache_dss_cinfo;
		*dispc_cinfo = dss.cache_dispc_cinfo;
		return 0;
	}

	min_fck_per_pck = CONFIG_OMAP2_DSS_MIN_FCK_PER_PCK;

	if (min_fck_per_pck &&
		req_pck * min_fck_per_pck > DISPC_MAX_FCK) {
		DSSERR("Requested pixel clock not possible with the current "
				"OMAP2_DSS_MIN_FCK_PER_PCK setting. Turning "
				"the constraint off.\n");
		min_fck_per_pck = 0;
	}

retry:
	memset(&best_dss, 0, sizeof(best_dss));
	memset(&best_dispc, 0, sizeof(best_dispc));

	if (cpu_is_omap24xx()) {
		struct dispc_clock_info cur_dispc;
		/* XXX can we change the clock on omap2? */
		fck = dss_clk_get_rate(DSS_CLK_FCK1);
		fck_div = 1;

		dispc_find_clk_divs(is_tft, req_pck, fck, &cur_dispc);
		match = 1;

		best_dss.fck = fck;
		best_dss.fck_div = fck_div;

		best_dispc = cur_dispc;

		goto found;
	} else if (cpu_is_omap34xx()) {
		if (cpu_is_omap3630())
			fck_div = 32;
		else
			fck_div = 16;

		for ( ; fck_div > 0; --fck_div) {
			struct dispc_clock_info cur_dispc;

			if (cpu_is_omap3630())
				fck = prate / fck_div ;
			else
				fck = prate / fck_div * 2;

			if (fck > DISPC_MAX_FCK)
				continue;

			if (min_fck_per_pck &&
					fck < req_pck * min_fck_per_pck)
				continue;

			match = 1;

			dispc_find_clk_divs(is_tft, req_pck, fck, &cur_dispc);

			if (abs(cur_dispc.pck - req_pck) <
					abs(best_dispc.pck - req_pck)) {

				best_dss.fck = fck;
				best_dss.fck_div = fck_div;

				best_dispc = cur_dispc;

				if (cur_dispc.pck == req_pck)
					goto found;
			}
		}
	} else if (cpu_is_omap34xx()){
		;/*do nothing for now*/
	} else
			BUG();

found:
	if (!match) {
		if (min_fck_per_pck) {
			DSSERR("Could not find suitable clock settings.\n"
					"Turning FCK/PCK constraint off and"
					"trying again.\n");
			min_fck_per_pck = 0;
			goto retry;
		}

		DSSERR("Could not find suitable clock settings.\n");

		return -EINVAL;
	}

	if (dss_cinfo)
		*dss_cinfo = best_dss;
	if (dispc_cinfo)
		*dispc_cinfo = best_dispc;

	dss.cache_req_pck = req_pck;
	dss.cache_prate = prate;
	dss.cache_dss_cinfo = best_dss;
	dss.cache_dispc_cinfo = best_dispc;

	return 0;
}