示例#1
0
static int dpi_set_dsi_clk(struct omap_dss_device *dssdev, bool is_tft,
		unsigned long pck_req, unsigned long *fck, int *lck_div,
		int *pck_div)
{
	struct dsi_clock_info dsi_cinfo;
	struct dispc_clock_info dispc_cinfo;
	int r;

	r = dsi_pll_calc_clock_div_pck(is_tft, pck_req, &dsi_cinfo,
			&dispc_cinfo);
	if (r)
		return r;

	r = dsi_pll_set_clock_div(&dsi_cinfo);
	if (r)
		return r;

	dss_select_dispc_clk_source(DSS_CLK_SRC_DSI_PLL_HSDIV_DISPC);

	r = dispc_set_clock_div(dssdev->manager->id, &dispc_cinfo);
	if (r)
		return r;

	*fck = dsi_cinfo.dsi_pll_hsdiv_dispc_clk;
	*lck_div = dispc_cinfo.lck_div;
	*pck_div = dispc_cinfo.pck_div;

	return 0;
}
示例#2
0
static int dpi_set_dispc_clk(struct omap_dss_device *dssdev, bool is_tft,
		unsigned long pck_req, unsigned long *fck, int *lck_div,
		int *pck_div)
{
	struct dss_clock_info dss_cinfo;
	struct dispc_clock_info dispc_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;

	r = dispc_set_clock_div(dssdev->manager->id, &dispc_cinfo);
	if (r)
		return r;

	*fck = dss_cinfo.fck;
	*lck_div = dispc_cinfo.lck_div;
	*pck_div = dispc_cinfo.pck_div;

	return 0;
}
示例#3
0
static int dpi_set_dispc_clk(int lcd_channel_ix,
	bool is_tft, unsigned long pck_req,
	unsigned long *fck, int *lck_div, int *pck_div)
{
	struct dss_clock_info dss_cinfo;
	struct dispc_clock_info dispc_cinfo;
	int r;

	if (cpu_is_omap44xx()) {
		printk(KERN_INFO "dpi set dispc clk");
	/*OMAP4: check this later?*/
		return 0;
	}

	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;

	r = dispc_set_clock_div(lcd_channel_ix, &dispc_cinfo);
	if (r)
		return r;

	*fck = dss_cinfo.fck;
	*lck_div = dispc_cinfo.lck_div;
	*pck_div = dispc_cinfo.pck_div;

	return 0;
}
示例#4
0
static int dpi_set_dsi_clk(struct omap_dss_device *dssdev, bool is_tft,
		unsigned long pck_req, unsigned long *fck, int *lck_div,
		int *pck_div)
{
	struct dsi_clock_info dsi_cinfo;
	struct dispc_clock_info dispc_cinfo;
	int r;

	r = dsi_pll_calc_clock_div_pck(dpi.dsidev, is_tft, pck_req,
			&dsi_cinfo, &dispc_cinfo);
	if (r)
		return r;

	r = dsi_pll_set_clock_div(dpi.dsidev, &dsi_cinfo);
	if (r)
		return r;

	dss_select_dispc_clk_source(dssdev->clocks.dispc.dispc_fclk_src);

	r = dispc_set_clock_div(dssdev->manager->id, &dispc_cinfo);
	if (r)
		return r;

	*fck = dsi_cinfo.dsi_pll_hsdiv_dispc_clk;
	*lck_div = dispc_cinfo.lck_div;
	*pck_div = dispc_cinfo.pck_div;

	return 0;
}
示例#5
0
static int dpi_set_dsi_clk(bool is_tft, unsigned long pck_req,
		unsigned long *fck, int *lck_div, int *pck_div)
{
	struct dsi_clock_info dsi_cinfo;
	struct dispc_clock_info dispc_cinfo;
	int r;

	r = dsi_pll_calc_clock_div_pck(is_tft, pck_req, &dsi_cinfo,
			&dispc_cinfo);
	if (r)
		return r;

	r = dsi_pll_set_clock_div(&dsi_cinfo);
	if (r)
		return r;

	dss_select_clk_source(0, 1);

	r = dispc_set_clock_div(&dispc_cinfo);
	if (r)
		return r;

	*fck = dsi_cinfo.dsi1_pll_fclk;
	*lck_div = dispc_cinfo.lck_div;
	*pck_div = dispc_cinfo.pck_div;

	return 0;
}
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;
}
示例#7
0
static int dpi_set_dsi_clk(int lcd_channel_ix, bool is_tft,
		unsigned long pck_req,
		unsigned long *fck, int *lck_div, int *pck_div)
{
	struct dsi_clock_info dsi_cinfo;
	struct dispc_clock_info dispc_cinfo;
	int r;
	printk(KERN_INFO "DPI set dsi clk");
	if (!cpu_is_omap44xx()) {
		r = dsi_pll_calc_clock_div_pck(lcd_channel_ix, is_tft,
			pck_req, &dsi_cinfo, &dispc_cinfo);
		if (r)
			return r;
	} else {
		dispc_cinfo.lck_div = 1;
		dispc_cinfo.pck_div = 4;
		dsi_cinfo.regn = 19;
		dsi_cinfo.regm = 150;
		dsi_cinfo.regm3 = 4;
		dsi_cinfo.regm4 = 4;
		dsi_cinfo.use_dss2_fck = true;
		dsi_cinfo.highfreq = 0;
		dsi_calc_clock_rates(&dsi_cinfo);
	}
	r = dsi_pll_set_clock_div(lcd_channel_ix, &dsi_cinfo);
	if (r)
		return r;

	if (cpu_is_omap44xx())
		dss_select_clk_source_dsi(lcd_channel_ix, 1, 1);
	else
		dss_select_clk_source(0, 1);

	r = dispc_set_clock_div(lcd_channel_ix, &dispc_cinfo);
	if (r)
		return r;

	*fck = dsi_cinfo.dsi1_pll_fclk;
	*lck_div = dispc_cinfo.lck_div;
	*pck_div = dispc_cinfo.pck_div;

	return 0;
}
示例#8
0
static int dpi_set_dispc_clk(bool is_tft, unsigned long pck_req,
		unsigned long *fck, int *lck_div, int *pck_div)
{
	struct dispc_clock_info cinfo;
	int r;

	r = dispc_calc_clock_div(is_tft, pck_req, &cinfo);
	if (r)
		return r;

	r = dispc_set_clock_div(&cinfo);
	if (r)
		return r;

	*fck = cinfo.fck;
	*lck_div = cinfo.lck_div;
	*pck_div = cinfo.pck_div;

	return 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;
}
示例#10
0
static int sdi_display_enable(struct omap_display *display)
{
	struct dispc_clock_info cinfo;
	u16 lck_div, pck_div;
	unsigned long fck;
	struct omap_panel *panel = display->panel;
	unsigned long pck;
	int r;

	if (display->state != OMAP_DSS_DISPLAY_DISABLED) {
		DSSERR("display already enabled\n");
		return -EINVAL;
	}

	twl4030_enable_regulator(RES_VAUX1);

	sdi_pad_config(display, 1);

	/* In case of skip_init sdi_init has already enabled the clocks */
	if (!sdi.skip_init)
		dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK1);

	sdi_basic_init();

	/* 15.5.9.1.2 */
	panel->config |= OMAP_DSS_LCD_RF | OMAP_DSS_LCD_ONOFF;

	dispc_set_pol_freq(panel);

	if (!sdi.skip_init)
		r = dispc_calc_clock_div(1, panel->timings.pixel_clock * 1000,
				&cinfo);
	else
		r = dispc_get_clock_div(&cinfo);

	if (r)
		goto err0;

	fck = cinfo.fck;
	lck_div = cinfo.lck_div;
	pck_div = cinfo.pck_div;

	pck = fck / lck_div / pck_div / 1000;

	if (pck != panel->timings.pixel_clock) {
		DSSWARN("Could not find exact pixel clock. Requested %d kHz, "
				"got %lu kHz\n",
				panel->timings.pixel_clock, pck);

		panel->timings.pixel_clock = pck;
	}


	dispc_set_lcd_timings(&panel->timings);

	r = dispc_set_clock_div(&cinfo);
	if (r)
		goto err1;

	if (!sdi.skip_init) {
		dss_sdi_init(display->hw_config.u.sdi.datapairs);
		r = dss_sdi_enable();
		if (r)
			goto err1;
		mdelay(2);
	}

	dispc_enable_lcd_out(1);

	r = panel->enable(display);
	if (r)
		goto err2;

	display->state = OMAP_DSS_DISPLAY_ACTIVE;

	sdi.skip_init = 0;

	return 0;
err2:
	dispc_enable_lcd_out(0);
err1:
err0:
	dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK1);
	twl4030_disable_regulator(RES_VAUX1);

	return r;
}
示例#11
0
int omapdss_sdi_display_enable(struct omap_dss_device *dssdev)
{
	struct omap_video_timings *t = &dssdev->panel.timings;
	struct dss_clock_info dss_cinfo;
	struct dispc_clock_info dispc_cinfo;
	u16 lck_div, pck_div;
	unsigned long fck;
	unsigned long pck;
	int r;

	r = omap_dss_start_device(dssdev);
	if (r) {
		DSSERR("failed to start device\n");
		goto err0;
	}

	r = regulator_enable(sdi.vdds_sdi_reg);
	if (r)
		goto err1;

	/* In case of skip_init sdi_init has already enabled the clocks */
	if (!sdi.skip_init)
		dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK1);

	sdi_basic_init();

	/* 15.5.9.1.2 */
	dssdev->panel.config |= OMAP_DSS_LCD_RF | OMAP_DSS_LCD_ONOFF;

	dispc_set_pol_freq(dssdev->panel.config, dssdev->panel.acbi,
			dssdev->panel.acb);

	if (!sdi.skip_init) {
		r = dss_calc_clock_div(1, t->pixel_clock * 1000,
				&dss_cinfo, &dispc_cinfo);
	} else {
		r = dss_get_clock_div(&dss_cinfo);
		r = dispc_get_clock_div(&dispc_cinfo);
	}

	if (r)
		goto err2;

	fck = dss_cinfo.fck;
	lck_div = dispc_cinfo.lck_div;
	pck_div = dispc_cinfo.pck_div;

	pck = fck / lck_div / pck_div / 1000;

	if (pck != t->pixel_clock) {
		DSSWARN("Could not find exact pixel clock. Requested %d kHz, "
				"got %lu kHz\n",
				t->pixel_clock, pck);

		t->pixel_clock = pck;
	}


	dispc_set_lcd_timings(t);

	r = dss_set_clock_div(&dss_cinfo);
	if (r)
		goto err2;

	r = dispc_set_clock_div(&dispc_cinfo);
	if (r)
		goto err2;

	if (!sdi.skip_init) {
		dss_sdi_init(dssdev->phy.sdi.datapairs);
		r = dss_sdi_enable();
		if (r)
			goto err1;
		mdelay(2);
	}

	dssdev->manager->enable(dssdev->manager);

	sdi.skip_init = 0;

	return 0;
err2:
	dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK1);
	regulator_disable(sdi.vdds_sdi_reg);
err1:
	omap_dss_stop_device(dssdev);
err0:
	return r;
}
示例#12
0
int omapdss_rfbi_display_enable(struct omap_dss_device *dssdev)
{
        int r;

        struct dispc_clock_info dispc_cinfo;

	struct omap_video_timings timings = {
                       .hsw            = 1,
                       .hfp            = 1,
                       .hbp            = 1,
                       .vsw            = 1,
                       .vfp            = 0,
                       .vbp            = 0,
		};

        r = omap_dss_start_device(dssdev);
        if (r) {
                DSSERR("RFBI: failed to start device\n");
                return r;
        }

	r = rfbi_runtime_get();
	if (r) {
		DSSERR("RFBI: failed to get runtime\n");
		goto err0;
	}


        r = omap_dispc_register_isr(framedone_callback, NULL,
                        DISPC_IRQ_FRAMEDONE);
        if (r) {
                DSSERR("RFBI: can't get FRAMEDONE irq\n");
                goto err1;
        }

        dispc_set_parallel_interface_mode(dssdev->manager->id,
                        OMAP_DSS_PARALLELMODE_RFBI);

	dispc_enable_fifohandcheck(dssdev->manager->id, 1);

        dispc_set_lcd_display_type(dssdev->manager->id,
                        OMAP_DSS_LCD_DISPLAY_TFT);

        dispc_set_tft_data_lines(dssdev->manager->id, dssdev->ctrl.pixel_size);

	dispc_set_lcd_timings(dssdev->manager->id, &timings);

	r = dispc_set_clock_div(dssdev->manager->id, &dispc_cinfo);
	if (r) {
		DSSERR("RFBI: Failed to set dispc clocks\n");
		goto err1;
	}

        rfbi_configure(dssdev->phy.rfbi.channel,
                               dssdev->ctrl.pixel_size,
                               dssdev->phy.rfbi.data_lines);

        rfbi_set_timings(dssdev->phy.rfbi.channel,
                         &dssdev->ctrl.rfbi_timings);


        return 0;
err1:
        rfbi_runtime_put();
err0:
        omap_dss_stop_device(dssdev);
        return r;
}
EXPORT_SYMBOL(omapdss_rfbi_display_enable);

void omapdss_rfbi_display_disable(struct omap_dss_device *dssdev)
{
        omap_dispc_unregister_isr(framedone_callback, NULL,
                        DISPC_IRQ_FRAMEDONE);
        omap_dss_stop_device(dssdev);

        rfbi_runtime_put();
}
示例#13
0
static int sdi_display_enable(struct omap_dss_device *dssdev)
{
	struct omap_video_timings *t = &dssdev->panel.timings;
	struct dss_clock_info dss_cinfo;
	struct dispc_clock_info dispc_cinfo;
	u16 lck_div, pck_div;
	unsigned long fck;
	unsigned long pck;
	int r;

	r = omap_dss_start_device(dssdev);
	if (r) {
		DSSERR("failed to start device\n");
		goto err0;
	}

	if (dssdev->state != OMAP_DSS_DISPLAY_DISABLED) {
		DSSERR("dssdev already enabled\n");
		r = -EINVAL;
		goto err1;
	}

	/* In case of skip_init sdi_init has already enabled the clocks */
	if (!sdi.skip_init)
		dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK1);

	sdi_basic_init();

	/* 15.5.9.1.2 */
	dssdev->panel.config |= OMAP_DSS_LCD_RF | OMAP_DSS_LCD_ONOFF;

	/* TODO: update for LCD2 here */
	dispc_set_pol_freq(OMAP_DSS_CHANNEL_LCD, dssdev->panel.config,
			dssdev->panel.acbi, dssdev->panel.acb);

	if (!sdi.skip_init) {
		r = dss_calc_clock_div(1, t->pixel_clock * 1000,
				&dss_cinfo, &dispc_cinfo);
	} else {
		r = dss_get_clock_div(&dss_cinfo);
		r = dispc_get_clock_div(&dispc_cinfo);
	}

	if (r)
		goto err2;

	fck = dss_cinfo.fck;
	lck_div = dispc_cinfo.lck_div;
	pck_div = dispc_cinfo.pck_div;

	pck = fck / lck_div / pck_div / 1000;

	if (pck != t->pixel_clock) {
		DSSWARN("Could not find exact pixel clock. Requested %d kHz, "
				"got %lu kHz\n",
				t->pixel_clock, pck);

		t->pixel_clock = pck;
	}

	/* TODO: if needed, add LCD2 support here*/
	dispc_set_lcd_timings(OMAP_DSS_CHANNEL_LCD, t);

	r = dss_set_clock_div(&dss_cinfo);
	if (r)
		goto err2;

	r = dispc_set_clock_div(&dispc_cinfo);
	if (r)
		goto err2;

	if (!sdi.skip_init) {
		dss_sdi_init(dssdev->phy.sdi.datapairs);
		r = dss_sdi_enable();
		if (r)
			goto err1;
		mdelay(2);
	}

	/* TODO: change here if LCD2 support is needed */
	dispc_enable_lcd_out(OMAP_DSS_CHANNEL_LCD, 1);

	if (dssdev->driver->enable) {
		r = dssdev->driver->enable(dssdev);
		if (r)
			goto err3;
	}

	dssdev->state = OMAP_DSS_DISPLAY_ACTIVE;

	sdi.skip_init = 0;

	return 0;
err3:
	/* TODO: change here if LCD2 support is needed */
	dispc_enable_lcd_out(OMAP_DSS_CHANNEL_LCD, 0);
err2:
	dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK1);
err1:
	omap_dss_stop_device(dssdev);
err0:
	return r;
}