2009-08-05 16:18:44 +03:00
/*
* linux / drivers / video / omap2 / dss / sdi . c
*
* Copyright ( C ) 2009 Nokia Corporation
* Author : Tomi Valkeinen < tomi . valkeinen @ nokia . com >
*
* 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 "SDI"
# include <linux/kernel.h>
# include <linux/delay.h>
# include <linux/err.h>
2010-03-17 13:35:21 +01:00
# include <linux/regulator/consumer.h>
2011-07-10 13:20:26 -04:00
# include <linux/export.h>
2012-02-20 16:57:37 +02:00
# include <linux/platform_device.h>
2009-08-05 16:18:44 +03:00
2011-05-11 14:05:07 +03:00
# include <video/omapdss.h>
2009-08-05 16:18:44 +03:00
# include "dss.h"
static struct {
bool update_enabled ;
2010-03-17 13:35:21 +01:00
struct regulator * vdds_sdi_reg ;
2009-08-05 16:18:44 +03:00
} sdi ;
2010-12-02 11:27:10 +00:00
static void sdi_basic_init ( struct omap_dss_device * dssdev )
2009-08-05 16:18:44 +03:00
{
2011-08-22 17:41:57 +05:30
dispc_mgr_set_io_pad_mode ( DSS_IO_PAD_MODE_BYPASS ) ;
dispc_mgr_enable_stallmode ( dssdev - > manager - > id , false ) ;
2010-12-02 11:27:10 +00:00
2011-08-16 13:45:15 +03:00
dispc_mgr_set_lcd_display_type ( dssdev - > manager - > id ,
2010-12-02 11:27:10 +00:00
OMAP_DSS_LCD_DISPLAY_TFT ) ;
2009-08-05 16:18:44 +03:00
2011-08-16 13:45:15 +03:00
dispc_mgr_set_tft_data_lines ( dssdev - > manager - > id , 24 ) ;
2009-08-05 16:18:44 +03:00
dispc_lcd_enable_signal_polarity ( 1 ) ;
}
2010-01-12 15:12:07 +02:00
int omapdss_sdi_display_enable ( struct omap_dss_device * dssdev )
2009-08-05 16:18:44 +03:00
{
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 ;
2011-06-23 16:38:21 +03:00
if ( dssdev - > manager = = NULL ) {
DSSERR ( " failed to enable display: no manager \n " ) ;
return - ENODEV ;
}
2009-08-05 16:18:44 +03:00
r = omap_dss_start_device ( dssdev ) ;
if ( r ) {
DSSERR ( " failed to start device \n " ) ;
2011-05-27 10:52:19 +03:00
goto err_start_dev ;
2009-08-05 16:18:44 +03:00
}
2010-03-17 13:35:21 +01:00
r = regulator_enable ( sdi . vdds_sdi_reg ) ;
if ( r )
2011-05-27 10:52:19 +03:00
goto err_reg_enable ;
2010-03-17 13:35:21 +01:00
2011-05-27 10:52:19 +03:00
r = dispc_runtime_get ( ) ;
if ( r )
goto err_get_dispc ;
2009-08-05 16:18:44 +03:00
2010-12-02 11:27:10 +00:00
sdi_basic_init ( dssdev ) ;
2009-08-05 16:18:44 +03:00
/* 15.5.9.1.2 */
dssdev - > panel . config | = OMAP_DSS_LCD_RF | OMAP_DSS_LCD_ONOFF ;
2011-08-16 13:45:15 +03:00
dispc_mgr_set_pol_freq ( dssdev - > manager - > id , dssdev - > panel . config ,
2010-12-02 11:27:11 +00:00
dssdev - > panel . acbi , dssdev - > panel . acb ) ;
2009-08-05 16:18:44 +03:00
2011-03-02 12:29:27 +02:00
r = dss_calc_clock_div ( 1 , t - > pixel_clock * 1000 ,
& dss_cinfo , & dispc_cinfo ) ;
2009-08-05 16:18:44 +03:00
if ( r )
2011-05-27 10:52:19 +03:00
goto err_calc_clock_div ;
2009-08-05 16:18:44 +03:00
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 ;
}
2012-04-26 20:10:46 +05:30
dss_mgr_set_timings ( dssdev - > manager , t ) ;
2009-08-05 16:18:44 +03:00
r = dss_set_clock_div ( & dss_cinfo ) ;
if ( r )
2011-05-27 10:52:19 +03:00
goto err_set_dss_clock_div ;
2009-08-05 16:18:44 +03:00
2011-08-16 13:45:15 +03:00
r = dispc_mgr_set_clock_div ( dssdev - > manager - > id , & dispc_cinfo ) ;
2009-08-05 16:18:44 +03:00
if ( r )
2011-05-27 10:52:19 +03:00
goto err_set_dispc_clock_div ;
2009-08-05 16:18:44 +03:00
2011-03-02 12:29:27 +02:00
dss_sdi_init ( dssdev - > phy . sdi . datapairs ) ;
r = dss_sdi_enable ( ) ;
if ( r )
2011-05-27 10:52:19 +03:00
goto err_sdi_enable ;
2011-03-02 12:29:27 +02:00
mdelay ( 2 ) ;
2009-08-05 16:18:44 +03:00
2011-11-21 13:42:58 +02:00
r = dss_mgr_enable ( dssdev - > manager ) ;
if ( r )
goto err_mgr_enable ;
2009-08-05 16:18:44 +03:00
return 0 ;
2011-05-27 10:52:19 +03:00
2011-11-21 13:42:58 +02:00
err_mgr_enable :
dss_sdi_disable ( ) ;
2011-05-27 10:52:19 +03:00
err_sdi_enable :
err_set_dispc_clock_div :
err_set_dss_clock_div :
err_calc_clock_div :
dispc_runtime_put ( ) ;
err_get_dispc :
2010-03-17 13:35:21 +01:00
regulator_disable ( sdi . vdds_sdi_reg ) ;
2011-05-27 10:52:19 +03:00
err_reg_enable :
2009-08-05 16:18:44 +03:00
omap_dss_stop_device ( dssdev ) ;
2011-05-27 10:52:19 +03:00
err_start_dev :
2009-08-05 16:18:44 +03:00
return r ;
}
2010-01-12 15:12:07 +02:00
EXPORT_SYMBOL ( omapdss_sdi_display_enable ) ;
2009-08-05 16:18:44 +03:00
2010-01-12 15:12:07 +02:00
void omapdss_sdi_display_disable ( struct omap_dss_device * dssdev )
2009-08-05 16:18:44 +03:00
{
2011-11-04 10:22:46 +02:00
dss_mgr_disable ( dssdev - > manager ) ;
2009-08-05 16:18:44 +03:00
dss_sdi_disable ( ) ;
2011-05-27 10:52:19 +03:00
dispc_runtime_put ( ) ;
2009-08-05 16:18:44 +03:00
2010-03-17 13:35:21 +01:00
regulator_disable ( sdi . vdds_sdi_reg ) ;
2009-08-05 16:18:44 +03:00
omap_dss_stop_device ( dssdev ) ;
}
2010-01-12 15:12:07 +02:00
EXPORT_SYMBOL ( omapdss_sdi_display_disable ) ;
2009-08-05 16:18:44 +03:00
int sdi_init_display ( struct omap_dss_device * dssdev )
{
DSSDBG ( " SDI init \n " ) ;
2011-02-22 15:53:46 +02:00
if ( sdi . vdds_sdi_reg = = NULL ) {
struct regulator * vdds_sdi ;
vdds_sdi = dss_get_vdds_sdi ( ) ;
if ( IS_ERR ( vdds_sdi ) ) {
DSSERR ( " can't get VDDS_SDI regulator \n " ) ;
return PTR_ERR ( vdds_sdi ) ;
}
sdi . vdds_sdi_reg = vdds_sdi ;
}
2009-08-05 16:18:44 +03:00
return 0 ;
}
2012-02-20 16:57:37 +02:00
static int omap_sdi_probe ( struct platform_device * pdev )
2009-08-05 16:18:44 +03:00
{
return 0 ;
}
2012-02-20 16:57:37 +02:00
static int omap_sdi_remove ( struct platform_device * pdev )
2009-08-05 16:18:44 +03:00
{
2012-02-20 16:57:37 +02:00
return 0 ;
}
static struct platform_driver omap_sdi_driver = {
. probe = omap_sdi_probe ,
. remove = omap_sdi_remove ,
. driver = {
. name = " omapdss_sdi " ,
. owner = THIS_MODULE ,
} ,
} ;
int sdi_init_platform_driver ( void )
{
return platform_driver_register ( & omap_sdi_driver ) ;
}
void sdi_uninit_platform_driver ( void )
{
platform_driver_unregister ( & omap_sdi_driver ) ;
2009-08-05 16:18:44 +03:00
}