Merge branch 'for-linus' of git://gitorious.org/linux-omap-dss2/linux
* 'for-linus' of git://gitorious.org/linux-omap-dss2/linux: (49 commits) OMAP: DSS2: Taal: Fix TE when resuming OMAP: DSS2: Taal: Fix ESD check OMAP: DSS2: OMAPFB: Constify some function parameters OMAP: DSS2: OMAPFB: install omapfb.h OMAP: DSS2: DSI: add error prints OMAP: DSS2: TPO-TD03MTEA1: fix function names OMAP: DSS2: DSI: add dsi_vc_dcs_read_2() helper OMAP: DSS2: OMAPFB: Remove FB_OMAP2_FORCE_AUTO_UPDATE OMAP: DSS2: DSI: remove external TE support OMAP: DSS2: move timing functions OMAP: DSS2: move set/get_wss() OMAP: DSS2: move enable/disable/suspend/resume OMAP: DSS2: move update() and sync() OMAP: DSS2: move set/get_update_mode() OMAP: DSS2: move enable/get_te() OMAP: DSS2: move get_recommended_bpp() OMAP: DSS2: move get_resolution() OMAP: DSS2: move enable/disable_channel to overlay manager OMAP: DSS2: move wait_vsync() OMAP: DSS2: move get/set_rotate() ...
This commit is contained in:
Коммит
3a5b27bf6f
|
@ -541,10 +541,6 @@ static struct regulator_init_data sdp3430_vdac = {
|
|||
|
||||
/* VPLL2 for digital video outputs */
|
||||
static struct regulator_consumer_supply sdp3430_vpll2_supplies[] = {
|
||||
{
|
||||
.supply = "vdvi",
|
||||
.dev = &sdp3430_lcd_device.dev,
|
||||
},
|
||||
{
|
||||
.supply = "vdds_dsi",
|
||||
.dev = &sdp3430_dss_device.dev,
|
||||
|
|
|
@ -233,8 +233,12 @@ int omap_rfbi_setup_te(enum omap_rfbi_te_mode mode,
|
|||
void dsi_bus_lock(void);
|
||||
void dsi_bus_unlock(void);
|
||||
int dsi_vc_dcs_write(int channel, u8 *data, int len);
|
||||
int dsi_vc_dcs_write_0(int channel, u8 dcs_cmd);
|
||||
int dsi_vc_dcs_write_1(int channel, u8 dcs_cmd, u8 param);
|
||||
int dsi_vc_dcs_write_nosync(int channel, u8 *data, int len);
|
||||
int dsi_vc_dcs_read(int channel, u8 dcs_cmd, u8 *buf, int buflen);
|
||||
int dsi_vc_dcs_read_1(int channel, u8 dcs_cmd, u8 *data);
|
||||
int dsi_vc_dcs_read_2(int channel, u8 dcs_cmd, u16 *data);
|
||||
int dsi_vc_set_max_rx_packet_size(int channel, u16 len);
|
||||
int dsi_vc_send_null(int channel);
|
||||
int dsi_vc_send_bta_sync(int channel);
|
||||
|
@ -367,6 +371,10 @@ struct omap_overlay_manager {
|
|||
|
||||
int (*apply)(struct omap_overlay_manager *mgr);
|
||||
int (*wait_for_go)(struct omap_overlay_manager *mgr);
|
||||
int (*wait_for_vsync)(struct omap_overlay_manager *mgr);
|
||||
|
||||
int (*enable)(struct omap_overlay_manager *mgr);
|
||||
int (*disable)(struct omap_overlay_manager *mgr);
|
||||
};
|
||||
|
||||
struct omap_dss_device {
|
||||
|
@ -426,16 +434,11 @@ struct omap_dss_device {
|
|||
int acb; /* ac-bias pin frequency */
|
||||
|
||||
enum omap_panel_config config;
|
||||
|
||||
u8 recommended_bpp;
|
||||
|
||||
struct omap_dss_device *ctrl;
|
||||
} panel;
|
||||
|
||||
struct {
|
||||
u8 pixel_size;
|
||||
struct rfbi_timings rfbi_timings;
|
||||
struct omap_dss_device *panel;
|
||||
} ctrl;
|
||||
|
||||
int reset_gpio;
|
||||
|
@ -460,49 +463,6 @@ struct omap_dss_device {
|
|||
|
||||
enum omap_dss_display_state state;
|
||||
|
||||
int (*enable)(struct omap_dss_device *dssdev);
|
||||
void (*disable)(struct omap_dss_device *dssdev);
|
||||
|
||||
int (*suspend)(struct omap_dss_device *dssdev);
|
||||
int (*resume)(struct omap_dss_device *dssdev);
|
||||
|
||||
void (*get_resolution)(struct omap_dss_device *dssdev,
|
||||
u16 *xres, u16 *yres);
|
||||
int (*get_recommended_bpp)(struct omap_dss_device *dssdev);
|
||||
|
||||
int (*check_timings)(struct omap_dss_device *dssdev,
|
||||
struct omap_video_timings *timings);
|
||||
void (*set_timings)(struct omap_dss_device *dssdev,
|
||||
struct omap_video_timings *timings);
|
||||
void (*get_timings)(struct omap_dss_device *dssdev,
|
||||
struct omap_video_timings *timings);
|
||||
int (*update)(struct omap_dss_device *dssdev,
|
||||
u16 x, u16 y, u16 w, u16 h);
|
||||
int (*sync)(struct omap_dss_device *dssdev);
|
||||
int (*wait_vsync)(struct omap_dss_device *dssdev);
|
||||
|
||||
int (*set_update_mode)(struct omap_dss_device *dssdev,
|
||||
enum omap_dss_update_mode);
|
||||
enum omap_dss_update_mode (*get_update_mode)
|
||||
(struct omap_dss_device *dssdev);
|
||||
|
||||
int (*enable_te)(struct omap_dss_device *dssdev, bool enable);
|
||||
int (*get_te)(struct omap_dss_device *dssdev);
|
||||
|
||||
u8 (*get_rotate)(struct omap_dss_device *dssdev);
|
||||
int (*set_rotate)(struct omap_dss_device *dssdev, u8 rotate);
|
||||
|
||||
bool (*get_mirror)(struct omap_dss_device *dssdev);
|
||||
int (*set_mirror)(struct omap_dss_device *dssdev, bool enable);
|
||||
|
||||
int (*run_test)(struct omap_dss_device *dssdev, int test);
|
||||
int (*memory_read)(struct omap_dss_device *dssdev,
|
||||
void *buf, size_t size,
|
||||
u16 x, u16 y, u16 w, u16 h);
|
||||
|
||||
int (*set_wss)(struct omap_dss_device *dssdev, u32 wss);
|
||||
u32 (*get_wss)(struct omap_dss_device *dssdev);
|
||||
|
||||
/* platform specific */
|
||||
int (*platform_enable)(struct omap_dss_device *dssdev);
|
||||
void (*platform_disable)(struct omap_dss_device *dssdev);
|
||||
|
@ -522,11 +482,17 @@ struct omap_dss_driver {
|
|||
int (*resume)(struct omap_dss_device *display);
|
||||
int (*run_test)(struct omap_dss_device *display, int test);
|
||||
|
||||
void (*setup_update)(struct omap_dss_device *dssdev,
|
||||
u16 x, u16 y, u16 w, u16 h);
|
||||
int (*set_update_mode)(struct omap_dss_device *dssdev,
|
||||
enum omap_dss_update_mode);
|
||||
enum omap_dss_update_mode (*get_update_mode)(
|
||||
struct omap_dss_device *dssdev);
|
||||
|
||||
int (*update)(struct omap_dss_device *dssdev,
|
||||
u16 x, u16 y, u16 w, u16 h);
|
||||
int (*sync)(struct omap_dss_device *dssdev);
|
||||
|
||||
int (*enable_te)(struct omap_dss_device *dssdev, bool enable);
|
||||
int (*wait_for_te)(struct omap_dss_device *dssdev);
|
||||
int (*get_te)(struct omap_dss_device *dssdev);
|
||||
|
||||
u8 (*get_rotate)(struct omap_dss_device *dssdev);
|
||||
int (*set_rotate)(struct omap_dss_device *dssdev, u8 rotate);
|
||||
|
@ -537,6 +503,20 @@ struct omap_dss_driver {
|
|||
int (*memory_read)(struct omap_dss_device *dssdev,
|
||||
void *buf, size_t size,
|
||||
u16 x, u16 y, u16 w, u16 h);
|
||||
|
||||
void (*get_resolution)(struct omap_dss_device *dssdev,
|
||||
u16 *xres, u16 *yres);
|
||||
int (*get_recommended_bpp)(struct omap_dss_device *dssdev);
|
||||
|
||||
int (*check_timings)(struct omap_dss_device *dssdev,
|
||||
struct omap_video_timings *timings);
|
||||
void (*set_timings)(struct omap_dss_device *dssdev,
|
||||
struct omap_video_timings *timings);
|
||||
void (*get_timings)(struct omap_dss_device *dssdev,
|
||||
struct omap_video_timings *timings);
|
||||
|
||||
int (*set_wss)(struct omap_dss_device *dssdev, u32 wss);
|
||||
u32 (*get_wss)(struct omap_dss_device *dssdev);
|
||||
};
|
||||
|
||||
int omap_dss_register_driver(struct omap_dss_driver *);
|
||||
|
@ -561,6 +541,10 @@ struct omap_overlay_manager *omap_dss_get_overlay_manager(int num);
|
|||
int omap_dss_get_num_overlays(void);
|
||||
struct omap_overlay *omap_dss_get_overlay(int num);
|
||||
|
||||
void omapdss_default_get_resolution(struct omap_dss_device *dssdev,
|
||||
u16 *xres, u16 *yres);
|
||||
int omapdss_default_get_recommended_bpp(struct omap_dss_device *dssdev);
|
||||
|
||||
typedef void (*omap_dispc_isr_t) (void *arg, u32 mask);
|
||||
int omap_dispc_register_isr(omap_dispc_isr_t isr, void *arg, u32 mask);
|
||||
int omap_dispc_unregister_isr(omap_dispc_isr_t isr, void *arg, u32 mask);
|
||||
|
@ -572,4 +556,35 @@ int omap_dispc_wait_for_irq_interruptible_timeout(u32 irqmask,
|
|||
#define to_dss_driver(x) container_of((x), struct omap_dss_driver, driver)
|
||||
#define to_dss_device(x) container_of((x), struct omap_dss_device, dev)
|
||||
|
||||
void omapdss_dsi_vc_enable_hs(int channel, bool enable);
|
||||
int omapdss_dsi_enable_te(struct omap_dss_device *dssdev, bool enable);
|
||||
|
||||
int omap_dsi_prepare_update(struct omap_dss_device *dssdev,
|
||||
u16 *x, u16 *y, u16 *w, u16 *h);
|
||||
int omap_dsi_update(struct omap_dss_device *dssdev,
|
||||
int channel,
|
||||
u16 x, u16 y, u16 w, u16 h,
|
||||
void (*callback)(int, void *), void *data);
|
||||
|
||||
int omapdss_dsi_display_enable(struct omap_dss_device *dssdev);
|
||||
void omapdss_dsi_display_disable(struct omap_dss_device *dssdev);
|
||||
|
||||
int omapdss_dpi_display_enable(struct omap_dss_device *dssdev);
|
||||
void omapdss_dpi_display_disable(struct omap_dss_device *dssdev);
|
||||
void dpi_set_timings(struct omap_dss_device *dssdev,
|
||||
struct omap_video_timings *timings);
|
||||
int dpi_check_timings(struct omap_dss_device *dssdev,
|
||||
struct omap_video_timings *timings);
|
||||
|
||||
int omapdss_sdi_display_enable(struct omap_dss_device *dssdev);
|
||||
void omapdss_sdi_display_disable(struct omap_dss_device *dssdev);
|
||||
|
||||
int omapdss_rfbi_display_enable(struct omap_dss_device *dssdev);
|
||||
void omapdss_rfbi_display_disable(struct omap_dss_device *dssdev);
|
||||
int omap_rfbi_prepare_update(struct omap_dss_device *dssdev,
|
||||
u16 *x, u16 *y, u16 *w, u16 *h);
|
||||
int omap_rfbi_update(struct omap_dss_device *dssdev,
|
||||
u16 x, u16 y, u16 w, u16 h,
|
||||
void (*callback)(void *), void *data);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -24,6 +24,7 @@
|
|||
#include <linux/platform_device.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/lcd.h>
|
||||
|
||||
#include <plat/board-ams-delta.h>
|
||||
#include <mach/hardware.h>
|
||||
|
@ -32,6 +33,71 @@
|
|||
|
||||
#define AMS_DELTA_DEFAULT_CONTRAST 112
|
||||
|
||||
#define AMS_DELTA_MAX_CONTRAST 0x00FF
|
||||
#define AMS_DELTA_LCD_POWER 0x0100
|
||||
|
||||
|
||||
/* LCD class device section */
|
||||
|
||||
static int ams_delta_lcd;
|
||||
|
||||
static int ams_delta_lcd_set_power(struct lcd_device *dev, int power)
|
||||
{
|
||||
if (power == FB_BLANK_UNBLANK) {
|
||||
if (!(ams_delta_lcd & AMS_DELTA_LCD_POWER)) {
|
||||
omap_writeb(ams_delta_lcd & AMS_DELTA_MAX_CONTRAST,
|
||||
OMAP_PWL_ENABLE);
|
||||
omap_writeb(1, OMAP_PWL_CLK_ENABLE);
|
||||
ams_delta_lcd |= AMS_DELTA_LCD_POWER;
|
||||
}
|
||||
} else {
|
||||
if (ams_delta_lcd & AMS_DELTA_LCD_POWER) {
|
||||
omap_writeb(0, OMAP_PWL_ENABLE);
|
||||
omap_writeb(0, OMAP_PWL_CLK_ENABLE);
|
||||
ams_delta_lcd &= ~AMS_DELTA_LCD_POWER;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ams_delta_lcd_set_contrast(struct lcd_device *dev, int value)
|
||||
{
|
||||
if ((value >= 0) && (value <= AMS_DELTA_MAX_CONTRAST)) {
|
||||
omap_writeb(value, OMAP_PWL_ENABLE);
|
||||
ams_delta_lcd &= ~AMS_DELTA_MAX_CONTRAST;
|
||||
ams_delta_lcd |= value;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_LCD_CLASS_DEVICE
|
||||
static int ams_delta_lcd_get_power(struct lcd_device *dev)
|
||||
{
|
||||
if (ams_delta_lcd & AMS_DELTA_LCD_POWER)
|
||||
return FB_BLANK_UNBLANK;
|
||||
else
|
||||
return FB_BLANK_POWERDOWN;
|
||||
}
|
||||
|
||||
static int ams_delta_lcd_get_contrast(struct lcd_device *dev)
|
||||
{
|
||||
if (!(ams_delta_lcd & AMS_DELTA_LCD_POWER))
|
||||
return 0;
|
||||
|
||||
return ams_delta_lcd & AMS_DELTA_MAX_CONTRAST;
|
||||
}
|
||||
|
||||
static struct lcd_ops ams_delta_lcd_ops = {
|
||||
.get_power = ams_delta_lcd_get_power,
|
||||
.set_power = ams_delta_lcd_set_power,
|
||||
.get_contrast = ams_delta_lcd_get_contrast,
|
||||
.set_contrast = ams_delta_lcd_set_contrast,
|
||||
};
|
||||
#endif
|
||||
|
||||
|
||||
/* omapfb panel section */
|
||||
|
||||
static int ams_delta_panel_init(struct lcd_panel *panel,
|
||||
struct omapfb_device *fbdev)
|
||||
{
|
||||
|
@ -48,10 +114,6 @@ static int ams_delta_panel_enable(struct lcd_panel *panel)
|
|||
AMS_DELTA_LATCH2_LCD_NDISP);
|
||||
ams_delta_latch2_write(AMS_DELTA_LATCH2_LCD_VBLEN,
|
||||
AMS_DELTA_LATCH2_LCD_VBLEN);
|
||||
|
||||
omap_writeb(1, OMAP_PWL_CLK_ENABLE);
|
||||
omap_writeb(AMS_DELTA_DEFAULT_CONTRAST, OMAP_PWL_ENABLE);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -91,8 +153,31 @@ static struct lcd_panel ams_delta_panel = {
|
|||
.get_caps = ams_delta_panel_get_caps,
|
||||
};
|
||||
|
||||
|
||||
/* platform driver section */
|
||||
|
||||
static int ams_delta_panel_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct lcd_device *lcd_device = NULL;
|
||||
#ifdef CONFIG_LCD_CLASS_DEVICE
|
||||
int ret;
|
||||
|
||||
lcd_device = lcd_device_register("omapfb", &pdev->dev, NULL,
|
||||
&ams_delta_lcd_ops);
|
||||
|
||||
if (IS_ERR(lcd_device)) {
|
||||
ret = PTR_ERR(lcd_device);
|
||||
dev_err(&pdev->dev, "failed to register device\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
platform_set_drvdata(pdev, lcd_device);
|
||||
lcd_device->props.max_contrast = AMS_DELTA_MAX_CONTRAST;
|
||||
#endif
|
||||
|
||||
ams_delta_lcd_set_contrast(lcd_device, AMS_DELTA_DEFAULT_CONTRAST);
|
||||
ams_delta_lcd_set_power(lcd_device, FB_BLANK_UNBLANK);
|
||||
|
||||
omapfb_register_panel(&ams_delta_panel);
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -486,10 +486,11 @@ static int set_color_mode(struct omapfb_plane_struct *plane,
|
|||
return 0;
|
||||
case 12:
|
||||
var->bits_per_pixel = 16;
|
||||
plane->color_mode = OMAPFB_COLOR_RGB444;
|
||||
return 0;
|
||||
case 16:
|
||||
plane->color_mode = OMAPFB_COLOR_RGB565;
|
||||
if (plane->fbdev->panel->bpp == 12)
|
||||
plane->color_mode = OMAPFB_COLOR_RGB444;
|
||||
else
|
||||
plane->color_mode = OMAPFB_COLOR_RGB565;
|
||||
return 0;
|
||||
default:
|
||||
return -EINVAL;
|
||||
|
|
|
@ -13,10 +13,28 @@ config PANEL_SHARP_LS037V7DW01
|
|||
help
|
||||
LCD Panel used in TI's SDP3430 and EVM boards
|
||||
|
||||
config PANEL_SHARP_LQ043T1DG01
|
||||
tristate "Sharp LQ043T1DG01 LCD Panel"
|
||||
depends on OMAP2_DSS
|
||||
help
|
||||
LCD Panel used in TI's OMAP3517 EVM boards
|
||||
|
||||
config PANEL_TAAL
|
||||
tristate "Taal DSI Panel"
|
||||
depends on OMAP2_DSS_DSI
|
||||
help
|
||||
Taal DSI command mode panel from TPO.
|
||||
|
||||
config PANEL_TOPPOLY_TDO35S
|
||||
tristate "Toppoly TDO35S LCD Panel support"
|
||||
depends on OMAP2_DSS
|
||||
help
|
||||
LCD Panel used in CM-T35
|
||||
|
||||
config PANEL_TPO_TD043MTEA1
|
||||
tristate "TPO TD043MTEA1 LCD Panel"
|
||||
depends on OMAP2_DSS && I2C
|
||||
help
|
||||
LCD Panel used in OMAP3 Pandora
|
||||
|
||||
endmenu
|
||||
|
|
|
@ -1,4 +1,7 @@
|
|||
obj-$(CONFIG_PANEL_GENERIC) += panel-generic.o
|
||||
obj-$(CONFIG_PANEL_SHARP_LS037V7DW01) += panel-sharp-ls037v7dw01.o
|
||||
obj-$(CONFIG_PANEL_SHARP_LQ043T1DG01) += panel-sharp-lq043t1dg01.o
|
||||
|
||||
obj-$(CONFIG_PANEL_TAAL) += panel-taal.o
|
||||
obj-$(CONFIG_PANEL_TOPPOLY_TDO35S) += panel-toppoly-tdo35s.o
|
||||
obj-$(CONFIG_PANEL_TPO_TD043MTEA1) += panel-tpo-td043mtea1.o
|
||||
|
|
|
@ -35,6 +35,35 @@ static struct omap_video_timings generic_panel_timings = {
|
|||
.vbp = 7,
|
||||
};
|
||||
|
||||
static int generic_panel_power_on(struct omap_dss_device *dssdev)
|
||||
{
|
||||
int r;
|
||||
|
||||
r = omapdss_dpi_display_enable(dssdev);
|
||||
if (r)
|
||||
goto err0;
|
||||
|
||||
if (dssdev->platform_enable) {
|
||||
r = dssdev->platform_enable(dssdev);
|
||||
if (r)
|
||||
goto err1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
err1:
|
||||
omapdss_dpi_display_disable(dssdev);
|
||||
err0:
|
||||
return r;
|
||||
}
|
||||
|
||||
static void generic_panel_power_off(struct omap_dss_device *dssdev)
|
||||
{
|
||||
if (dssdev->platform_disable)
|
||||
dssdev->platform_disable(dssdev);
|
||||
|
||||
omapdss_dpi_display_disable(dssdev);
|
||||
}
|
||||
|
||||
static int generic_panel_probe(struct omap_dss_device *dssdev)
|
||||
{
|
||||
dssdev->panel.config = OMAP_DSS_LCD_TFT;
|
||||
|
@ -51,27 +80,40 @@ static int generic_panel_enable(struct omap_dss_device *dssdev)
|
|||
{
|
||||
int r = 0;
|
||||
|
||||
if (dssdev->platform_enable)
|
||||
r = dssdev->platform_enable(dssdev);
|
||||
r = generic_panel_power_on(dssdev);
|
||||
if (r)
|
||||
return r;
|
||||
|
||||
return r;
|
||||
dssdev->state = OMAP_DSS_DISPLAY_ACTIVE;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void generic_panel_disable(struct omap_dss_device *dssdev)
|
||||
{
|
||||
if (dssdev->platform_disable)
|
||||
dssdev->platform_disable(dssdev);
|
||||
generic_panel_power_off(dssdev);
|
||||
|
||||
dssdev->state = OMAP_DSS_DISPLAY_DISABLED;
|
||||
}
|
||||
|
||||
static int generic_panel_suspend(struct omap_dss_device *dssdev)
|
||||
{
|
||||
generic_panel_disable(dssdev);
|
||||
generic_panel_power_off(dssdev);
|
||||
dssdev->state = OMAP_DSS_DISPLAY_SUSPENDED;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int generic_panel_resume(struct omap_dss_device *dssdev)
|
||||
{
|
||||
return generic_panel_enable(dssdev);
|
||||
int r = 0;
|
||||
|
||||
r = generic_panel_power_on(dssdev);
|
||||
if (r)
|
||||
return r;
|
||||
|
||||
dssdev->state = OMAP_DSS_DISPLAY_ACTIVE;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct omap_dss_driver generic_driver = {
|
||||
|
|
|
@ -0,0 +1,159 @@
|
|||
/*
|
||||
* LCD panel driver for Sharp LQ043T1DG01
|
||||
*
|
||||
* Copyright (C) 2009 Texas Instruments Inc
|
||||
* Author: Vaibhav Hiremath <hvaibhav@ti.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/>.
|
||||
*/
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/device.h>
|
||||
#include <linux/err.h>
|
||||
|
||||
#include <plat/display.h>
|
||||
|
||||
static struct omap_video_timings sharp_lq_timings = {
|
||||
.x_res = 480,
|
||||
.y_res = 272,
|
||||
|
||||
.pixel_clock = 9000,
|
||||
|
||||
.hsw = 42,
|
||||
.hfp = 3,
|
||||
.hbp = 2,
|
||||
|
||||
.vsw = 11,
|
||||
.vfp = 3,
|
||||
.vbp = 2,
|
||||
};
|
||||
|
||||
static int sharp_lq_panel_power_on(struct omap_dss_device *dssdev)
|
||||
{
|
||||
int r;
|
||||
|
||||
r = omapdss_dpi_display_enable(dssdev);
|
||||
if (r)
|
||||
goto err0;
|
||||
|
||||
/* wait couple of vsyncs until enabling the LCD */
|
||||
msleep(50);
|
||||
|
||||
if (dssdev->platform_enable) {
|
||||
r = dssdev->platform_enable(dssdev);
|
||||
if (r)
|
||||
goto err1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
err1:
|
||||
omapdss_dpi_display_disable(dssdev);
|
||||
err0:
|
||||
return r;
|
||||
}
|
||||
|
||||
static void sharp_lq_panel_power_off(struct omap_dss_device *dssdev)
|
||||
{
|
||||
if (dssdev->platform_disable)
|
||||
dssdev->platform_disable(dssdev);
|
||||
|
||||
/* wait at least 5 vsyncs after disabling the LCD */
|
||||
msleep(100);
|
||||
|
||||
omapdss_dpi_display_disable(dssdev);
|
||||
}
|
||||
|
||||
static int sharp_lq_panel_probe(struct omap_dss_device *dssdev)
|
||||
{
|
||||
|
||||
dssdev->panel.config = OMAP_DSS_LCD_TFT | OMAP_DSS_LCD_IVS |
|
||||
OMAP_DSS_LCD_IHS | OMAP_DSS_LCD_IEO;
|
||||
dssdev->panel.acb = 0x0;
|
||||
dssdev->panel.timings = sharp_lq_timings;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void sharp_lq_panel_remove(struct omap_dss_device *dssdev)
|
||||
{
|
||||
}
|
||||
|
||||
static int sharp_lq_panel_enable(struct omap_dss_device *dssdev)
|
||||
{
|
||||
int r = 0;
|
||||
|
||||
r = sharp_lq_panel_power_on(dssdev);
|
||||
if (r)
|
||||
return r;
|
||||
|
||||
dssdev->state = OMAP_DSS_DISPLAY_ACTIVE;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void sharp_lq_panel_disable(struct omap_dss_device *dssdev)
|
||||
{
|
||||
sharp_lq_panel_power_off(dssdev);
|
||||
|
||||
dssdev->state = OMAP_DSS_DISPLAY_DISABLED;
|
||||
}
|
||||
|
||||
static int sharp_lq_panel_suspend(struct omap_dss_device *dssdev)
|
||||
{
|
||||
sharp_lq_panel_power_off(dssdev);
|
||||
dssdev->state = OMAP_DSS_DISPLAY_SUSPENDED;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int sharp_lq_panel_resume(struct omap_dss_device *dssdev)
|
||||
{
|
||||
int r = 0;
|
||||
|
||||
r = sharp_lq_panel_power_on(dssdev);
|
||||
if (r)
|
||||
return r;
|
||||
|
||||
dssdev->state = OMAP_DSS_DISPLAY_ACTIVE;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct omap_dss_driver sharp_lq_driver = {
|
||||
.probe = sharp_lq_panel_probe,
|
||||
.remove = sharp_lq_panel_remove,
|
||||
|
||||
.enable = sharp_lq_panel_enable,
|
||||
.disable = sharp_lq_panel_disable,
|
||||
.suspend = sharp_lq_panel_suspend,
|
||||
.resume = sharp_lq_panel_resume,
|
||||
|
||||
.driver = {
|
||||
.name = "sharp_lq_panel",
|
||||
.owner = THIS_MODULE,
|
||||
},
|
||||
};
|
||||
|
||||
static int __init sharp_lq_panel_drv_init(void)
|
||||
{
|
||||
return omap_dss_register_driver(&sharp_lq_driver);
|
||||
}
|
||||
|
||||
static void __exit sharp_lq_panel_drv_exit(void)
|
||||
{
|
||||
omap_dss_unregister_driver(&sharp_lq_driver);
|
||||
}
|
||||
|
||||
module_init(sharp_lq_panel_drv_init);
|
||||
module_exit(sharp_lq_panel_drv_exit);
|
||||
MODULE_LICENSE("GPL");
|
|
@ -20,19 +20,10 @@
|
|||
#include <linux/module.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/device.h>
|
||||
#include <linux/regulator/consumer.h>
|
||||
#include <linux/err.h>
|
||||
|
||||
#include <plat/display.h>
|
||||
|
||||
struct sharp_data {
|
||||
/* XXX This regulator should actually be in SDP board file, not here,
|
||||
* as it doesn't actually power the LCD, but something else that
|
||||
* affects the output to LCD (I think. Somebody clarify). It doesn't do
|
||||
* harm here, as SDP is the only board using this currently */
|
||||
struct regulator *vdvi_reg;
|
||||
};
|
||||
|
||||
static struct omap_video_timings sharp_ls_timings = {
|
||||
.x_res = 480,
|
||||
.y_res = 640,
|
||||
|
@ -50,77 +41,81 @@ static struct omap_video_timings sharp_ls_timings = {
|
|||
|
||||
static int sharp_ls_panel_probe(struct omap_dss_device *dssdev)
|
||||
{
|
||||
struct sharp_data *sd;
|
||||
|
||||
dssdev->panel.config = OMAP_DSS_LCD_TFT | OMAP_DSS_LCD_IVS |
|
||||
OMAP_DSS_LCD_IHS;
|
||||
dssdev->panel.acb = 0x28;
|
||||
dssdev->panel.timings = sharp_ls_timings;
|
||||
|
||||
sd = kzalloc(sizeof(*sd), GFP_KERNEL);
|
||||
if (!sd)
|
||||
return -ENOMEM;
|
||||
|
||||
dev_set_drvdata(&dssdev->dev, sd);
|
||||
|
||||
sd->vdvi_reg = regulator_get(&dssdev->dev, "vdvi");
|
||||
if (IS_ERR(sd->vdvi_reg)) {
|
||||
kfree(sd);
|
||||
pr_err("failed to get VDVI regulator\n");
|
||||
return PTR_ERR(sd->vdvi_reg);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void sharp_ls_panel_remove(struct omap_dss_device *dssdev)
|
||||
{
|
||||
struct sharp_data *sd = dev_get_drvdata(&dssdev->dev);
|
||||
|
||||
regulator_put(sd->vdvi_reg);
|
||||
|
||||
kfree(sd);
|
||||
}
|
||||
|
||||
static int sharp_ls_panel_enable(struct omap_dss_device *dssdev)
|
||||
static int sharp_ls_power_on(struct omap_dss_device *dssdev)
|
||||
{
|
||||
struct sharp_data *sd = dev_get_drvdata(&dssdev->dev);
|
||||
int r = 0;
|
||||
|
||||
r = omapdss_dpi_display_enable(dssdev);
|
||||
if (r)
|
||||
goto err0;
|
||||
|
||||
/* wait couple of vsyncs until enabling the LCD */
|
||||
msleep(50);
|
||||
|
||||
regulator_enable(sd->vdvi_reg);
|
||||
|
||||
if (dssdev->platform_enable)
|
||||
if (dssdev->platform_enable) {
|
||||
r = dssdev->platform_enable(dssdev);
|
||||
if (r)
|
||||
goto err1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
err1:
|
||||
omapdss_dpi_display_disable(dssdev);
|
||||
err0:
|
||||
return r;
|
||||
}
|
||||
|
||||
static void sharp_ls_power_off(struct omap_dss_device *dssdev)
|
||||
{
|
||||
if (dssdev->platform_disable)
|
||||
dssdev->platform_disable(dssdev);
|
||||
|
||||
/* wait at least 5 vsyncs after disabling the LCD */
|
||||
|
||||
msleep(100);
|
||||
|
||||
omapdss_dpi_display_disable(dssdev);
|
||||
}
|
||||
|
||||
static int sharp_ls_panel_enable(struct omap_dss_device *dssdev)
|
||||
{
|
||||
int r;
|
||||
r = sharp_ls_power_on(dssdev);
|
||||
dssdev->state = OMAP_DSS_DISPLAY_ACTIVE;
|
||||
return r;
|
||||
}
|
||||
|
||||
static void sharp_ls_panel_disable(struct omap_dss_device *dssdev)
|
||||
{
|
||||
struct sharp_data *sd = dev_get_drvdata(&dssdev->dev);
|
||||
|
||||
if (dssdev->platform_disable)
|
||||
dssdev->platform_disable(dssdev);
|
||||
|
||||
regulator_disable(sd->vdvi_reg);
|
||||
|
||||
/* wait at least 5 vsyncs after disabling the LCD */
|
||||
|
||||
msleep(100);
|
||||
sharp_ls_power_off(dssdev);
|
||||
dssdev->state = OMAP_DSS_DISPLAY_DISABLED;
|
||||
}
|
||||
|
||||
static int sharp_ls_panel_suspend(struct omap_dss_device *dssdev)
|
||||
{
|
||||
sharp_ls_panel_disable(dssdev);
|
||||
sharp_ls_power_off(dssdev);
|
||||
dssdev->state = OMAP_DSS_DISPLAY_SUSPENDED;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int sharp_ls_panel_resume(struct omap_dss_device *dssdev)
|
||||
{
|
||||
return sharp_ls_panel_enable(dssdev);
|
||||
int r;
|
||||
r = sharp_ls_power_on(dssdev);
|
||||
dssdev->state = OMAP_DSS_DISPLAY_ACTIVE;
|
||||
return r;
|
||||
}
|
||||
|
||||
static struct omap_dss_driver sharp_ls_driver = {
|
||||
|
|
|
@ -63,6 +63,8 @@
|
|||
/* #define TAAL_USE_ESD_CHECK */
|
||||
#define TAAL_ESD_CHECK_PERIOD msecs_to_jiffies(5000)
|
||||
|
||||
static int _taal_enable_te(struct omap_dss_device *dssdev, bool enable);
|
||||
|
||||
struct taal_data {
|
||||
struct backlight_device *bldev;
|
||||
|
||||
|
@ -510,15 +512,12 @@ static int taal_probe(struct omap_dss_device *dssdev)
|
|||
if (td->esd_wq == NULL) {
|
||||
dev_err(&dssdev->dev, "can't create ESD workqueue\n");
|
||||
r = -ENOMEM;
|
||||
goto err2;
|
||||
goto err1;
|
||||
}
|
||||
INIT_DELAYED_WORK_DEFERRABLE(&td->esd_work, taal_esd_work);
|
||||
|
||||
dev_set_drvdata(&dssdev->dev, td);
|
||||
|
||||
dssdev->get_timings = taal_get_timings;
|
||||
dssdev->get_resolution = taal_get_resolution;
|
||||
|
||||
/* if no platform set_backlight() defined, presume DSI backlight
|
||||
* control */
|
||||
if (!dssdev->set_backlight)
|
||||
|
@ -528,7 +527,7 @@ static int taal_probe(struct omap_dss_device *dssdev)
|
|||
&taal_bl_ops);
|
||||
if (IS_ERR(bldev)) {
|
||||
r = PTR_ERR(bldev);
|
||||
goto err1;
|
||||
goto err2;
|
||||
}
|
||||
|
||||
td->bldev = bldev;
|
||||
|
@ -621,14 +620,12 @@ static void taal_remove(struct omap_dss_device *dssdev)
|
|||
kfree(td);
|
||||
}
|
||||
|
||||
static int taal_enable(struct omap_dss_device *dssdev)
|
||||
static int taal_power_on(struct omap_dss_device *dssdev)
|
||||
{
|
||||
struct taal_data *td = dev_get_drvdata(&dssdev->dev);
|
||||
u8 id1, id2, id3;
|
||||
int r;
|
||||
|
||||
dev_dbg(&dssdev->dev, "enable\n");
|
||||
|
||||
if (dssdev->platform_enable) {
|
||||
r = dssdev->platform_enable(dssdev);
|
||||
if (r)
|
||||
|
@ -638,6 +635,16 @@ static int taal_enable(struct omap_dss_device *dssdev)
|
|||
/* it seems we have to wait a bit until taal is ready */
|
||||
msleep(5);
|
||||
|
||||
dsi_bus_lock();
|
||||
|
||||
r = omapdss_dsi_display_enable(dssdev);
|
||||
if (r) {
|
||||
dev_err(&dssdev->dev, "failed to enable DSI\n");
|
||||
goto err0;
|
||||
}
|
||||
|
||||
omapdss_dsi_vc_enable_hs(TCH, false);
|
||||
|
||||
r = taal_sleep_out(td);
|
||||
if (r)
|
||||
goto err;
|
||||
|
@ -661,6 +668,10 @@ static int taal_enable(struct omap_dss_device *dssdev)
|
|||
|
||||
taal_dcs_write_0(DCS_DISPLAY_ON);
|
||||
|
||||
r = _taal_enable_te(dssdev, td->te_enabled);
|
||||
if (r)
|
||||
goto err;
|
||||
|
||||
#ifdef TAAL_USE_ESD_CHECK
|
||||
queue_delayed_work(td->esd_wq, &td->esd_work, TAAL_ESD_CHECK_PERIOD);
|
||||
#endif
|
||||
|
@ -676,19 +687,27 @@ static int taal_enable(struct omap_dss_device *dssdev)
|
|||
td->intro_printed = true;
|
||||
}
|
||||
|
||||
omapdss_dsi_vc_enable_hs(TCH, true);
|
||||
|
||||
dsi_bus_unlock();
|
||||
|
||||
return 0;
|
||||
err:
|
||||
dsi_bus_unlock();
|
||||
|
||||
omapdss_dsi_display_disable(dssdev);
|
||||
err0:
|
||||
if (dssdev->platform_disable)
|
||||
dssdev->platform_disable(dssdev);
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
static void taal_disable(struct omap_dss_device *dssdev)
|
||||
static void taal_power_off(struct omap_dss_device *dssdev)
|
||||
{
|
||||
struct taal_data *td = dev_get_drvdata(&dssdev->dev);
|
||||
|
||||
dev_dbg(&dssdev->dev, "disable\n");
|
||||
dsi_bus_lock();
|
||||
|
||||
cancel_delayed_work(&td->esd_work);
|
||||
|
||||
|
@ -698,41 +717,124 @@ static void taal_disable(struct omap_dss_device *dssdev)
|
|||
/* wait a bit so that the message goes through */
|
||||
msleep(10);
|
||||
|
||||
omapdss_dsi_display_disable(dssdev);
|
||||
|
||||
if (dssdev->platform_disable)
|
||||
dssdev->platform_disable(dssdev);
|
||||
|
||||
td->enabled = 0;
|
||||
|
||||
dsi_bus_unlock();
|
||||
}
|
||||
|
||||
static int taal_enable(struct omap_dss_device *dssdev)
|
||||
{
|
||||
int r;
|
||||
dev_dbg(&dssdev->dev, "enable\n");
|
||||
|
||||
if (dssdev->state != OMAP_DSS_DISPLAY_DISABLED)
|
||||
return -EINVAL;
|
||||
|
||||
r = taal_power_on(dssdev);
|
||||
if (r)
|
||||
return r;
|
||||
|
||||
dssdev->state = OMAP_DSS_DISPLAY_ACTIVE;
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
static void taal_disable(struct omap_dss_device *dssdev)
|
||||
{
|
||||
dev_dbg(&dssdev->dev, "disable\n");
|
||||
|
||||
if (dssdev->state == OMAP_DSS_DISPLAY_ACTIVE)
|
||||
taal_power_off(dssdev);
|
||||
|
||||
dssdev->state = OMAP_DSS_DISPLAY_DISABLED;
|
||||
}
|
||||
|
||||
static int taal_suspend(struct omap_dss_device *dssdev)
|
||||
{
|
||||
struct taal_data *td = dev_get_drvdata(&dssdev->dev);
|
||||
struct backlight_device *bldev = td->bldev;
|
||||
dev_dbg(&dssdev->dev, "suspend\n");
|
||||
|
||||
bldev->props.power = FB_BLANK_POWERDOWN;
|
||||
taal_bl_update_status(bldev);
|
||||
if (dssdev->state != OMAP_DSS_DISPLAY_ACTIVE)
|
||||
return -EINVAL;
|
||||
|
||||
taal_power_off(dssdev);
|
||||
dssdev->state = OMAP_DSS_DISPLAY_SUSPENDED;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int taal_resume(struct omap_dss_device *dssdev)
|
||||
{
|
||||
struct taal_data *td = dev_get_drvdata(&dssdev->dev);
|
||||
struct backlight_device *bldev = td->bldev;
|
||||
int r;
|
||||
dev_dbg(&dssdev->dev, "resume\n");
|
||||
|
||||
bldev->props.power = FB_BLANK_UNBLANK;
|
||||
taal_bl_update_status(bldev);
|
||||
if (dssdev->state != OMAP_DSS_DISPLAY_SUSPENDED)
|
||||
return -EINVAL;
|
||||
|
||||
r = taal_power_on(dssdev);
|
||||
dssdev->state = OMAP_DSS_DISPLAY_ACTIVE;
|
||||
return r;
|
||||
}
|
||||
|
||||
static void taal_framedone_cb(int err, void *data)
|
||||
{
|
||||
struct omap_dss_device *dssdev = data;
|
||||
dev_dbg(&dssdev->dev, "framedone, err %d\n", err);
|
||||
dsi_bus_unlock();
|
||||
}
|
||||
|
||||
static int taal_update(struct omap_dss_device *dssdev,
|
||||
u16 x, u16 y, u16 w, u16 h)
|
||||
{
|
||||
struct taal_data *td = dev_get_drvdata(&dssdev->dev);
|
||||
int r;
|
||||
|
||||
dev_dbg(&dssdev->dev, "update %d, %d, %d x %d\n", x, y, w, h);
|
||||
|
||||
dsi_bus_lock();
|
||||
|
||||
if (!td->enabled) {
|
||||
r = 0;
|
||||
goto err;
|
||||
}
|
||||
|
||||
r = omap_dsi_prepare_update(dssdev, &x, &y, &w, &h);
|
||||
if (r)
|
||||
goto err;
|
||||
|
||||
r = taal_set_update_window(x, y, w, h);
|
||||
if (r)
|
||||
goto err;
|
||||
|
||||
r = omap_dsi_update(dssdev, TCH, x, y, w, h,
|
||||
taal_framedone_cb, dssdev);
|
||||
if (r)
|
||||
goto err;
|
||||
|
||||
/* note: no bus_unlock here. unlock is in framedone_cb */
|
||||
return 0;
|
||||
err:
|
||||
dsi_bus_unlock();
|
||||
return r;
|
||||
}
|
||||
|
||||
static int taal_sync(struct omap_dss_device *dssdev)
|
||||
{
|
||||
dev_dbg(&dssdev->dev, "sync\n");
|
||||
|
||||
dsi_bus_lock();
|
||||
dsi_bus_unlock();
|
||||
|
||||
dev_dbg(&dssdev->dev, "sync done\n");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void taal_setup_update(struct omap_dss_device *dssdev,
|
||||
u16 x, u16 y, u16 w, u16 h)
|
||||
{
|
||||
taal_set_update_window(x, y, w, h);
|
||||
}
|
||||
|
||||
static int taal_enable_te(struct omap_dss_device *dssdev, bool enable)
|
||||
static int _taal_enable_te(struct omap_dss_device *dssdev, bool enable)
|
||||
{
|
||||
struct taal_data *td = dev_get_drvdata(&dssdev->dev);
|
||||
int r;
|
||||
|
@ -744,25 +846,32 @@ static int taal_enable_te(struct omap_dss_device *dssdev, bool enable)
|
|||
else
|
||||
r = taal_dcs_write_0(DCS_TEAR_OFF);
|
||||
|
||||
omapdss_dsi_enable_te(dssdev, enable);
|
||||
|
||||
/* XXX for some reason, DSI TE breaks if we don't wait here.
|
||||
* Panel bug? Needs more studying */
|
||||
msleep(100);
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
static int taal_wait_te(struct omap_dss_device *dssdev)
|
||||
static int taal_enable_te(struct omap_dss_device *dssdev, bool enable)
|
||||
{
|
||||
int r;
|
||||
|
||||
dsi_bus_lock();
|
||||
|
||||
r = _taal_enable_te(dssdev, enable);
|
||||
|
||||
dsi_bus_unlock();
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
static int taal_get_te(struct omap_dss_device *dssdev)
|
||||
{
|
||||
struct taal_data *td = dev_get_drvdata(&dssdev->dev);
|
||||
long wait = msecs_to_jiffies(500);
|
||||
|
||||
if (!td->use_ext_te || !td->te_enabled)
|
||||
return 0;
|
||||
|
||||
INIT_COMPLETION(td->te_completion);
|
||||
wait = wait_for_completion_timeout(&td->te_completion, wait);
|
||||
if (wait == 0) {
|
||||
dev_err(&dssdev->dev, "timeout waiting TE\n");
|
||||
return -ETIME;
|
||||
}
|
||||
|
||||
return 0;
|
||||
return td->te_enabled;
|
||||
}
|
||||
|
||||
static int taal_rotate(struct omap_dss_device *dssdev, u8 rotate)
|
||||
|
@ -772,16 +881,21 @@ static int taal_rotate(struct omap_dss_device *dssdev, u8 rotate)
|
|||
|
||||
dev_dbg(&dssdev->dev, "rotate %d\n", rotate);
|
||||
|
||||
dsi_bus_lock();
|
||||
|
||||
if (td->enabled) {
|
||||
r = taal_set_addr_mode(rotate, td->mirror);
|
||||
|
||||
if (r)
|
||||
return r;
|
||||
goto err;
|
||||
}
|
||||
|
||||
td->rotate = rotate;
|
||||
|
||||
dsi_bus_unlock();
|
||||
return 0;
|
||||
err:
|
||||
dsi_bus_unlock();
|
||||
return r;
|
||||
}
|
||||
|
||||
static u8 taal_get_rotate(struct omap_dss_device *dssdev)
|
||||
|
@ -797,16 +911,20 @@ static int taal_mirror(struct omap_dss_device *dssdev, bool enable)
|
|||
|
||||
dev_dbg(&dssdev->dev, "mirror %d\n", enable);
|
||||
|
||||
dsi_bus_lock();
|
||||
if (td->enabled) {
|
||||
r = taal_set_addr_mode(td->rotate, enable);
|
||||
|
||||
if (r)
|
||||
return r;
|
||||
goto err;
|
||||
}
|
||||
|
||||
td->mirror = enable;
|
||||
|
||||
dsi_bus_unlock();
|
||||
return 0;
|
||||
err:
|
||||
dsi_bus_unlock();
|
||||
return r;
|
||||
}
|
||||
|
||||
static bool taal_get_mirror(struct omap_dss_device *dssdev)
|
||||
|
@ -820,17 +938,23 @@ static int taal_run_test(struct omap_dss_device *dssdev, int test_num)
|
|||
u8 id1, id2, id3;
|
||||
int r;
|
||||
|
||||
dsi_bus_lock();
|
||||
|
||||
r = taal_dcs_read_1(DCS_GET_ID1, &id1);
|
||||
if (r)
|
||||
return r;
|
||||
goto err;
|
||||
r = taal_dcs_read_1(DCS_GET_ID2, &id2);
|
||||
if (r)
|
||||
return r;
|
||||
goto err;
|
||||
r = taal_dcs_read_1(DCS_GET_ID3, &id3);
|
||||
if (r)
|
||||
return r;
|
||||
goto err;
|
||||
|
||||
dsi_bus_unlock();
|
||||
return 0;
|
||||
err:
|
||||
dsi_bus_unlock();
|
||||
return r;
|
||||
}
|
||||
|
||||
static int taal_memory_read(struct omap_dss_device *dssdev,
|
||||
|
@ -841,6 +965,10 @@ static int taal_memory_read(struct omap_dss_device *dssdev,
|
|||
int first = 1;
|
||||
int plen;
|
||||
unsigned buf_used = 0;
|
||||
struct taal_data *td = dev_get_drvdata(&dssdev->dev);
|
||||
|
||||
if (!td->enabled)
|
||||
return -ENODEV;
|
||||
|
||||
if (size < w * h * 3)
|
||||
return -ENOMEM;
|
||||
|
@ -849,6 +977,8 @@ static int taal_memory_read(struct omap_dss_device *dssdev,
|
|||
dssdev->panel.timings.x_res *
|
||||
dssdev->panel.timings.y_res * 3);
|
||||
|
||||
dsi_bus_lock();
|
||||
|
||||
/* plen 1 or 2 goes into short packet. until checksum error is fixed,
|
||||
* use short packets. plen 32 works, but bigger packets seem to cause
|
||||
* an error. */
|
||||
|
@ -857,11 +987,11 @@ static int taal_memory_read(struct omap_dss_device *dssdev,
|
|||
else
|
||||
plen = 2;
|
||||
|
||||
taal_setup_update(dssdev, x, y, w, h);
|
||||
taal_set_update_window(x, y, w, h);
|
||||
|
||||
r = dsi_vc_set_max_rx_packet_size(TCH, plen);
|
||||
if (r)
|
||||
return r;
|
||||
goto err0;
|
||||
|
||||
while (buf_used < size) {
|
||||
u8 dcs_cmd = first ? 0x2e : 0x3e;
|
||||
|
@ -894,7 +1024,8 @@ static int taal_memory_read(struct omap_dss_device *dssdev,
|
|||
|
||||
err:
|
||||
dsi_vc_set_max_rx_packet_size(TCH, 1);
|
||||
|
||||
err0:
|
||||
dsi_bus_unlock();
|
||||
return r;
|
||||
}
|
||||
|
||||
|
@ -939,8 +1070,11 @@ static void taal_esd_work(struct work_struct *work)
|
|||
}
|
||||
/* Self-diagnostics result is also shown on TE GPIO line. We need
|
||||
* to re-enable TE after self diagnostics */
|
||||
if (td->use_ext_te && td->te_enabled)
|
||||
taal_enable_te(dssdev, true);
|
||||
if (td->use_ext_te && td->te_enabled) {
|
||||
r = taal_dcs_write_1(DCS_TEAR_ON, 0);
|
||||
if (r)
|
||||
goto err;
|
||||
}
|
||||
|
||||
dsi_bus_unlock();
|
||||
|
||||
|
@ -958,6 +1092,20 @@ err:
|
|||
queue_delayed_work(td->esd_wq, &td->esd_work, TAAL_ESD_CHECK_PERIOD);
|
||||
}
|
||||
|
||||
static int taal_set_update_mode(struct omap_dss_device *dssdev,
|
||||
enum omap_dss_update_mode mode)
|
||||
{
|
||||
if (mode != OMAP_DSS_UPDATE_MANUAL)
|
||||
return -EINVAL;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static enum omap_dss_update_mode taal_get_update_mode(
|
||||
struct omap_dss_device *dssdev)
|
||||
{
|
||||
return OMAP_DSS_UPDATE_MANUAL;
|
||||
}
|
||||
|
||||
static struct omap_dss_driver taal_driver = {
|
||||
.probe = taal_probe,
|
||||
.remove = taal_remove,
|
||||
|
@ -967,9 +1115,18 @@ static struct omap_dss_driver taal_driver = {
|
|||
.suspend = taal_suspend,
|
||||
.resume = taal_resume,
|
||||
|
||||
.setup_update = taal_setup_update,
|
||||
.set_update_mode = taal_set_update_mode,
|
||||
.get_update_mode = taal_get_update_mode,
|
||||
|
||||
.update = taal_update,
|
||||
.sync = taal_sync,
|
||||
|
||||
.get_resolution = taal_get_resolution,
|
||||
.get_recommended_bpp = omapdss_default_get_recommended_bpp,
|
||||
|
||||
.enable_te = taal_enable_te,
|
||||
.wait_for_te = taal_wait_te,
|
||||
.get_te = taal_get_te,
|
||||
|
||||
.set_rotate = taal_rotate,
|
||||
.get_rotate = taal_get_rotate,
|
||||
.set_mirror = taal_mirror,
|
||||
|
@ -977,6 +1134,8 @@ static struct omap_dss_driver taal_driver = {
|
|||
.run_test = taal_run_test,
|
||||
.memory_read = taal_memory_read,
|
||||
|
||||
.get_timings = taal_get_timings,
|
||||
|
||||
.driver = {
|
||||
.name = "taal",
|
||||
.owner = THIS_MODULE,
|
||||
|
|
|
@ -0,0 +1,154 @@
|
|||
/*
|
||||
* LCD panel driver for Toppoly TDO35S
|
||||
*
|
||||
* Copyright (C) 2009 CompuLab, Ltd.
|
||||
* Author: Mike Rapoport <mike@compulab.co.il>
|
||||
*
|
||||
* Based on generic panel support
|
||||
* Copyright (C) 2008 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/>.
|
||||
*/
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/delay.h>
|
||||
|
||||
#include <plat/display.h>
|
||||
|
||||
static struct omap_video_timings toppoly_tdo_panel_timings = {
|
||||
/* 640 x 480 @ 60 Hz Reduced blanking VESA CVT 0.31M3-R */
|
||||
.x_res = 480,
|
||||
.y_res = 640,
|
||||
|
||||
.pixel_clock = 26000,
|
||||
|
||||
.hfp = 104,
|
||||
.hsw = 8,
|
||||
.hbp = 8,
|
||||
|
||||
.vfp = 4,
|
||||
.vsw = 2,
|
||||
.vbp = 2,
|
||||
};
|
||||
|
||||
static int toppoly_tdo_panel_power_on(struct omap_dss_device *dssdev)
|
||||
{
|
||||
int r;
|
||||
|
||||
r = omapdss_dpi_display_enable(dssdev);
|
||||
if (r)
|
||||
goto err0;
|
||||
|
||||
if (dssdev->platform_enable) {
|
||||
r = dssdev->platform_enable(dssdev);
|
||||
if (r)
|
||||
goto err1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
err1:
|
||||
omapdss_dpi_display_disable(dssdev);
|
||||
err0:
|
||||
return r;
|
||||
}
|
||||
|
||||
static void toppoly_tdo_panel_power_off(struct omap_dss_device *dssdev)
|
||||
{
|
||||
if (dssdev->platform_disable)
|
||||
dssdev->platform_disable(dssdev);
|
||||
|
||||
omapdss_dpi_display_disable(dssdev);
|
||||
}
|
||||
|
||||
static int toppoly_tdo_panel_probe(struct omap_dss_device *dssdev)
|
||||
{
|
||||
dssdev->panel.config = OMAP_DSS_LCD_TFT | OMAP_DSS_LCD_IVS |
|
||||
OMAP_DSS_LCD_IHS;
|
||||
dssdev->panel.timings = toppoly_tdo_panel_timings;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void toppoly_tdo_panel_remove(struct omap_dss_device *dssdev)
|
||||
{
|
||||
}
|
||||
|
||||
static int toppoly_tdo_panel_enable(struct omap_dss_device *dssdev)
|
||||
{
|
||||
int r = 0;
|
||||
|
||||
r = toppoly_tdo_panel_power_on(dssdev);
|
||||
if (r)
|
||||
return r;
|
||||
|
||||
dssdev->state = OMAP_DSS_DISPLAY_ACTIVE;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void toppoly_tdo_panel_disable(struct omap_dss_device *dssdev)
|
||||
{
|
||||
toppoly_tdo_panel_power_off(dssdev);
|
||||
|
||||
dssdev->state = OMAP_DSS_DISPLAY_DISABLED;
|
||||
}
|
||||
|
||||
static int toppoly_tdo_panel_suspend(struct omap_dss_device *dssdev)
|
||||
{
|
||||
toppoly_tdo_panel_power_off(dssdev);
|
||||
dssdev->state = OMAP_DSS_DISPLAY_SUSPENDED;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int toppoly_tdo_panel_resume(struct omap_dss_device *dssdev)
|
||||
{
|
||||
int r = 0;
|
||||
|
||||
r = toppoly_tdo_panel_power_on(dssdev);
|
||||
if (r)
|
||||
return r;
|
||||
|
||||
dssdev->state = OMAP_DSS_DISPLAY_ACTIVE;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct omap_dss_driver generic_driver = {
|
||||
.probe = toppoly_tdo_panel_probe,
|
||||
.remove = toppoly_tdo_panel_remove,
|
||||
|
||||
.enable = toppoly_tdo_panel_enable,
|
||||
.disable = toppoly_tdo_panel_disable,
|
||||
.suspend = toppoly_tdo_panel_suspend,
|
||||
.resume = toppoly_tdo_panel_resume,
|
||||
|
||||
.driver = {
|
||||
.name = "toppoly_tdo35s_panel",
|
||||
.owner = THIS_MODULE,
|
||||
},
|
||||
};
|
||||
|
||||
static int __init toppoly_tdo_panel_drv_init(void)
|
||||
{
|
||||
return omap_dss_register_driver(&generic_driver);
|
||||
}
|
||||
|
||||
static void __exit toppoly_tdo_panel_drv_exit(void)
|
||||
{
|
||||
omap_dss_unregister_driver(&generic_driver);
|
||||
}
|
||||
|
||||
module_init(toppoly_tdo_panel_drv_init);
|
||||
module_exit(toppoly_tdo_panel_drv_exit);
|
||||
MODULE_LICENSE("GPL");
|
|
@ -0,0 +1,528 @@
|
|||
/*
|
||||
* LCD panel driver for TPO TD043MTEA1
|
||||
*
|
||||
* Author: Gražvydas Ignotas <notasas@gmail.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*/
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/spi/spi.h>
|
||||
#include <linux/regulator/consumer.h>
|
||||
#include <linux/gpio.h>
|
||||
#include <linux/err.h>
|
||||
|
||||
#include <plat/display.h>
|
||||
|
||||
#define TPO_R02_MODE(x) ((x) & 7)
|
||||
#define TPO_R02_MODE_800x480 7
|
||||
#define TPO_R02_NCLK_RISING BIT(3)
|
||||
#define TPO_R02_HSYNC_HIGH BIT(4)
|
||||
#define TPO_R02_VSYNC_HIGH BIT(5)
|
||||
|
||||
#define TPO_R03_NSTANDBY BIT(0)
|
||||
#define TPO_R03_EN_CP_CLK BIT(1)
|
||||
#define TPO_R03_EN_VGL_PUMP BIT(2)
|
||||
#define TPO_R03_EN_PWM BIT(3)
|
||||
#define TPO_R03_DRIVING_CAP_100 BIT(4)
|
||||
#define TPO_R03_EN_PRE_CHARGE BIT(6)
|
||||
#define TPO_R03_SOFTWARE_CTL BIT(7)
|
||||
|
||||
#define TPO_R04_NFLIP_H BIT(0)
|
||||
#define TPO_R04_NFLIP_V BIT(1)
|
||||
#define TPO_R04_CP_CLK_FREQ_1H BIT(2)
|
||||
#define TPO_R04_VGL_FREQ_1H BIT(4)
|
||||
|
||||
#define TPO_R03_VAL_NORMAL (TPO_R03_NSTANDBY | TPO_R03_EN_CP_CLK | \
|
||||
TPO_R03_EN_VGL_PUMP | TPO_R03_EN_PWM | \
|
||||
TPO_R03_DRIVING_CAP_100 | TPO_R03_EN_PRE_CHARGE | \
|
||||
TPO_R03_SOFTWARE_CTL)
|
||||
|
||||
#define TPO_R03_VAL_STANDBY (TPO_R03_DRIVING_CAP_100 | \
|
||||
TPO_R03_EN_PRE_CHARGE | TPO_R03_SOFTWARE_CTL)
|
||||
|
||||
static const u16 tpo_td043_def_gamma[12] = {
|
||||
106, 200, 289, 375, 460, 543, 625, 705, 785, 864, 942, 1020
|
||||
};
|
||||
|
||||
struct tpo_td043_device {
|
||||
struct spi_device *spi;
|
||||
struct regulator *vcc_reg;
|
||||
u16 gamma[12];
|
||||
u32 mode;
|
||||
u32 hmirror:1;
|
||||
u32 vmirror:1;
|
||||
};
|
||||
|
||||
static int tpo_td043_write(struct spi_device *spi, u8 addr, u8 data)
|
||||
{
|
||||
struct spi_message m;
|
||||
struct spi_transfer xfer;
|
||||
u16 w;
|
||||
int r;
|
||||
|
||||
spi_message_init(&m);
|
||||
|
||||
memset(&xfer, 0, sizeof(xfer));
|
||||
|
||||
w = ((u16)addr << 10) | (1 << 8) | data;
|
||||
xfer.tx_buf = &w;
|
||||
xfer.bits_per_word = 16;
|
||||
xfer.len = 2;
|
||||
spi_message_add_tail(&xfer, &m);
|
||||
|
||||
r = spi_sync(spi, &m);
|
||||
if (r < 0)
|
||||
dev_warn(&spi->dev, "failed to write to LCD reg (%d)\n", r);
|
||||
return r;
|
||||
}
|
||||
|
||||
static void tpo_td043_write_gamma(struct spi_device *spi, u16 gamma[12])
|
||||
{
|
||||
u8 i, val;
|
||||
|
||||
/* gamma bits [9:8] */
|
||||
for (val = i = 0; i < 4; i++)
|
||||
val |= (gamma[i] & 0x300) >> ((i + 1) * 2);
|
||||
tpo_td043_write(spi, 0x11, val);
|
||||
|
||||
for (val = i = 0; i < 4; i++)
|
||||
val |= (gamma[i+4] & 0x300) >> ((i + 1) * 2);
|
||||
tpo_td043_write(spi, 0x12, val);
|
||||
|
||||
for (val = i = 0; i < 4; i++)
|
||||
val |= (gamma[i+8] & 0x300) >> ((i + 1) * 2);
|
||||
tpo_td043_write(spi, 0x13, val);
|
||||
|
||||
/* gamma bits [7:0] */
|
||||
for (val = i = 0; i < 12; i++)
|
||||
tpo_td043_write(spi, 0x14 + i, gamma[i] & 0xff);
|
||||
}
|
||||
|
||||
static int tpo_td043_write_mirror(struct spi_device *spi, bool h, bool v)
|
||||
{
|
||||
u8 reg4 = TPO_R04_NFLIP_H | TPO_R04_NFLIP_V | \
|
||||
TPO_R04_CP_CLK_FREQ_1H | TPO_R04_VGL_FREQ_1H;
|
||||
if (h)
|
||||
reg4 &= ~TPO_R04_NFLIP_H;
|
||||
if (v)
|
||||
reg4 &= ~TPO_R04_NFLIP_V;
|
||||
|
||||
return tpo_td043_write(spi, 4, reg4);
|
||||
}
|
||||
|
||||
static int tpo_td043_set_hmirror(struct omap_dss_device *dssdev, bool enable)
|
||||
{
|
||||
struct tpo_td043_device *tpo_td043 = dev_get_drvdata(&dssdev->dev);
|
||||
|
||||
tpo_td043->hmirror = enable;
|
||||
return tpo_td043_write_mirror(tpo_td043->spi, tpo_td043->hmirror,
|
||||
tpo_td043->vmirror);
|
||||
}
|
||||
|
||||
static bool tpo_td043_get_hmirror(struct omap_dss_device *dssdev)
|
||||
{
|
||||
struct tpo_td043_device *tpo_td043 = dev_get_drvdata(&dssdev->dev);
|
||||
|
||||
return tpo_td043->hmirror;
|
||||
}
|
||||
|
||||
static ssize_t tpo_td043_vmirror_show(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
struct tpo_td043_device *tpo_td043 = dev_get_drvdata(dev);
|
||||
|
||||
return snprintf(buf, PAGE_SIZE, "%d\n", tpo_td043->vmirror);
|
||||
}
|
||||
|
||||
static ssize_t tpo_td043_vmirror_store(struct device *dev,
|
||||
struct device_attribute *attr, const char *buf, size_t count)
|
||||
{
|
||||
struct tpo_td043_device *tpo_td043 = dev_get_drvdata(dev);
|
||||
long val;
|
||||
int ret;
|
||||
|
||||
ret = strict_strtol(buf, 0, &val);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
ret = tpo_td043_write_mirror(tpo_td043->spi, tpo_td043->hmirror, val);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
tpo_td043->vmirror = val;
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
static ssize_t tpo_td043_mode_show(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
struct tpo_td043_device *tpo_td043 = dev_get_drvdata(dev);
|
||||
|
||||
return snprintf(buf, PAGE_SIZE, "%d\n", tpo_td043->mode);
|
||||
}
|
||||
|
||||
static ssize_t tpo_td043_mode_store(struct device *dev,
|
||||
struct device_attribute *attr, const char *buf, size_t count)
|
||||
{
|
||||
struct tpo_td043_device *tpo_td043 = dev_get_drvdata(dev);
|
||||
long val;
|
||||
int ret;
|
||||
|
||||
ret = strict_strtol(buf, 0, &val);
|
||||
if (ret != 0 || val & ~7)
|
||||
return -EINVAL;
|
||||
|
||||
tpo_td043->mode = val;
|
||||
|
||||
val |= TPO_R02_NCLK_RISING;
|
||||
tpo_td043_write(tpo_td043->spi, 2, val);
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
static ssize_t tpo_td043_gamma_show(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
struct tpo_td043_device *tpo_td043 = dev_get_drvdata(dev);
|
||||
ssize_t len = 0;
|
||||
int ret;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(tpo_td043->gamma); i++) {
|
||||
ret = snprintf(buf + len, PAGE_SIZE - len, "%u ",
|
||||
tpo_td043->gamma[i]);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
len += ret;
|
||||
}
|
||||
buf[len - 1] = '\n';
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
static ssize_t tpo_td043_gamma_store(struct device *dev,
|
||||
struct device_attribute *attr, const char *buf, size_t count)
|
||||
{
|
||||
struct tpo_td043_device *tpo_td043 = dev_get_drvdata(dev);
|
||||
unsigned int g[12];
|
||||
int ret;
|
||||
int i;
|
||||
|
||||
ret = sscanf(buf, "%u %u %u %u %u %u %u %u %u %u %u %u",
|
||||
&g[0], &g[1], &g[2], &g[3], &g[4], &g[5],
|
||||
&g[6], &g[7], &g[8], &g[9], &g[10], &g[11]);
|
||||
|
||||
if (ret != 12)
|
||||
return -EINVAL;
|
||||
|
||||
for (i = 0; i < 12; i++)
|
||||
tpo_td043->gamma[i] = g[i];
|
||||
|
||||
tpo_td043_write_gamma(tpo_td043->spi, tpo_td043->gamma);
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
static DEVICE_ATTR(vmirror, S_IRUGO | S_IWUSR,
|
||||
tpo_td043_vmirror_show, tpo_td043_vmirror_store);
|
||||
static DEVICE_ATTR(mode, S_IRUGO | S_IWUSR,
|
||||
tpo_td043_mode_show, tpo_td043_mode_store);
|
||||
static DEVICE_ATTR(gamma, S_IRUGO | S_IWUSR,
|
||||
tpo_td043_gamma_show, tpo_td043_gamma_store);
|
||||
|
||||
static struct attribute *tpo_td043_attrs[] = {
|
||||
&dev_attr_vmirror.attr,
|
||||
&dev_attr_mode.attr,
|
||||
&dev_attr_gamma.attr,
|
||||
NULL,
|
||||
};
|
||||
|
||||
static struct attribute_group tpo_td043_attr_group = {
|
||||
.attrs = tpo_td043_attrs,
|
||||
};
|
||||
|
||||
static const struct omap_video_timings tpo_td043_timings = {
|
||||
.x_res = 800,
|
||||
.y_res = 480,
|
||||
|
||||
.pixel_clock = 36000,
|
||||
|
||||
.hsw = 1,
|
||||
.hfp = 68,
|
||||
.hbp = 214,
|
||||
|
||||
.vsw = 1,
|
||||
.vfp = 39,
|
||||
.vbp = 34,
|
||||
};
|
||||
|
||||
static int tpo_td043_power_on(struct omap_dss_device *dssdev)
|
||||
{
|
||||
struct tpo_td043_device *tpo_td043 = dev_get_drvdata(&dssdev->dev);
|
||||
int nreset_gpio = dssdev->reset_gpio;
|
||||
int r;
|
||||
|
||||
r = omapdss_dpi_display_enable(dssdev);
|
||||
if (r)
|
||||
goto err0;
|
||||
|
||||
if (dssdev->platform_enable) {
|
||||
r = dssdev->platform_enable(dssdev);
|
||||
if (r)
|
||||
goto err1;
|
||||
}
|
||||
|
||||
regulator_enable(tpo_td043->vcc_reg);
|
||||
|
||||
/* wait for power up */
|
||||
msleep(160);
|
||||
|
||||
if (gpio_is_valid(nreset_gpio))
|
||||
gpio_set_value(nreset_gpio, 1);
|
||||
|
||||
tpo_td043_write(tpo_td043->spi, 2,
|
||||
TPO_R02_MODE(tpo_td043->mode) | TPO_R02_NCLK_RISING);
|
||||
tpo_td043_write(tpo_td043->spi, 3, TPO_R03_VAL_NORMAL);
|
||||
tpo_td043_write(tpo_td043->spi, 0x20, 0xf0);
|
||||
tpo_td043_write(tpo_td043->spi, 0x21, 0xf0);
|
||||
tpo_td043_write_mirror(tpo_td043->spi, tpo_td043->hmirror,
|
||||
tpo_td043->vmirror);
|
||||
tpo_td043_write_gamma(tpo_td043->spi, tpo_td043->gamma);
|
||||
|
||||
return 0;
|
||||
err1:
|
||||
omapdss_dpi_display_disable(dssdev);
|
||||
err0:
|
||||
return r;
|
||||
}
|
||||
|
||||
static void tpo_td043_power_off(struct omap_dss_device *dssdev)
|
||||
{
|
||||
struct tpo_td043_device *tpo_td043 = dev_get_drvdata(&dssdev->dev);
|
||||
int nreset_gpio = dssdev->reset_gpio;
|
||||
|
||||
tpo_td043_write(tpo_td043->spi, 3,
|
||||
TPO_R03_VAL_STANDBY | TPO_R03_EN_PWM);
|
||||
|
||||
if (gpio_is_valid(nreset_gpio))
|
||||
gpio_set_value(nreset_gpio, 0);
|
||||
|
||||
/* wait for at least 2 vsyncs before cutting off power */
|
||||
msleep(50);
|
||||
|
||||
tpo_td043_write(tpo_td043->spi, 3, TPO_R03_VAL_STANDBY);
|
||||
|
||||
regulator_disable(tpo_td043->vcc_reg);
|
||||
|
||||
if (dssdev->platform_disable)
|
||||
dssdev->platform_disable(dssdev);
|
||||
|
||||
omapdss_dpi_display_disable(dssdev);
|
||||
}
|
||||
|
||||
static int tpo_td043_enable(struct omap_dss_device *dssdev)
|
||||
{
|
||||
int ret;
|
||||
|
||||
dev_dbg(&dssdev->dev, "enable\n");
|
||||
|
||||
ret = tpo_td043_power_on(dssdev);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
dssdev->state = OMAP_DSS_DISPLAY_ACTIVE;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void tpo_td043_disable(struct omap_dss_device *dssdev)
|
||||
{
|
||||
dev_dbg(&dssdev->dev, "disable\n");
|
||||
|
||||
tpo_td043_power_off(dssdev);
|
||||
|
||||
dssdev->state = OMAP_DSS_DISPLAY_DISABLED;
|
||||
}
|
||||
|
||||
static int tpo_td043_suspend(struct omap_dss_device *dssdev)
|
||||
{
|
||||
tpo_td043_power_off(dssdev);
|
||||
dssdev->state = OMAP_DSS_DISPLAY_SUSPENDED;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int tpo_td043_resume(struct omap_dss_device *dssdev)
|
||||
{
|
||||
int r = 0;
|
||||
|
||||
r = tpo_td043_power_on(dssdev);
|
||||
if (r)
|
||||
return r;
|
||||
|
||||
dssdev->state = OMAP_DSS_DISPLAY_ACTIVE;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int tpo_td043_probe(struct omap_dss_device *dssdev)
|
||||
{
|
||||
struct tpo_td043_device *tpo_td043 = dev_get_drvdata(&dssdev->dev);
|
||||
int nreset_gpio = dssdev->reset_gpio;
|
||||
int ret = 0;
|
||||
|
||||
dev_dbg(&dssdev->dev, "probe\n");
|
||||
|
||||
if (tpo_td043 == NULL) {
|
||||
dev_err(&dssdev->dev, "missing tpo_td043_device\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
dssdev->panel.config = OMAP_DSS_LCD_TFT | OMAP_DSS_LCD_IHS |
|
||||
OMAP_DSS_LCD_IVS | OMAP_DSS_LCD_IPC;
|
||||
dssdev->panel.timings = tpo_td043_timings;
|
||||
dssdev->ctrl.pixel_size = 24;
|
||||
|
||||
tpo_td043->mode = TPO_R02_MODE_800x480;
|
||||
memcpy(tpo_td043->gamma, tpo_td043_def_gamma, sizeof(tpo_td043->gamma));
|
||||
|
||||
tpo_td043->vcc_reg = regulator_get(&dssdev->dev, "vcc");
|
||||
if (IS_ERR(tpo_td043->vcc_reg)) {
|
||||
dev_err(&dssdev->dev, "failed to get LCD VCC regulator\n");
|
||||
ret = PTR_ERR(tpo_td043->vcc_reg);
|
||||
goto fail_regulator;
|
||||
}
|
||||
|
||||
if (gpio_is_valid(nreset_gpio)) {
|
||||
ret = gpio_request(nreset_gpio, "lcd reset");
|
||||
if (ret < 0) {
|
||||
dev_err(&dssdev->dev, "couldn't request reset GPIO\n");
|
||||
goto fail_gpio_req;
|
||||
}
|
||||
|
||||
ret = gpio_direction_output(nreset_gpio, 0);
|
||||
if (ret < 0) {
|
||||
dev_err(&dssdev->dev, "couldn't set GPIO direction\n");
|
||||
goto fail_gpio_direction;
|
||||
}
|
||||
}
|
||||
|
||||
ret = sysfs_create_group(&dssdev->dev.kobj, &tpo_td043_attr_group);
|
||||
if (ret)
|
||||
dev_warn(&dssdev->dev, "failed to create sysfs files\n");
|
||||
|
||||
return 0;
|
||||
|
||||
fail_gpio_direction:
|
||||
gpio_free(nreset_gpio);
|
||||
fail_gpio_req:
|
||||
regulator_put(tpo_td043->vcc_reg);
|
||||
fail_regulator:
|
||||
kfree(tpo_td043);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void tpo_td043_remove(struct omap_dss_device *dssdev)
|
||||
{
|
||||
struct tpo_td043_device *tpo_td043 = dev_get_drvdata(&dssdev->dev);
|
||||
int nreset_gpio = dssdev->reset_gpio;
|
||||
|
||||
dev_dbg(&dssdev->dev, "remove\n");
|
||||
|
||||
sysfs_remove_group(&dssdev->dev.kobj, &tpo_td043_attr_group);
|
||||
regulator_put(tpo_td043->vcc_reg);
|
||||
if (gpio_is_valid(nreset_gpio))
|
||||
gpio_free(nreset_gpio);
|
||||
}
|
||||
|
||||
static struct omap_dss_driver tpo_td043_driver = {
|
||||
.probe = tpo_td043_probe,
|
||||
.remove = tpo_td043_remove,
|
||||
|
||||
.enable = tpo_td043_enable,
|
||||
.disable = tpo_td043_disable,
|
||||
.suspend = tpo_td043_suspend,
|
||||
.resume = tpo_td043_resume,
|
||||
.set_mirror = tpo_td043_set_hmirror,
|
||||
.get_mirror = tpo_td043_get_hmirror,
|
||||
|
||||
.driver = {
|
||||
.name = "tpo_td043mtea1_panel",
|
||||
.owner = THIS_MODULE,
|
||||
},
|
||||
};
|
||||
|
||||
static int tpo_td043_spi_probe(struct spi_device *spi)
|
||||
{
|
||||
struct omap_dss_device *dssdev = spi->dev.platform_data;
|
||||
struct tpo_td043_device *tpo_td043;
|
||||
int ret;
|
||||
|
||||
if (dssdev == NULL) {
|
||||
dev_err(&spi->dev, "missing dssdev\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
spi->bits_per_word = 16;
|
||||
spi->mode = SPI_MODE_0;
|
||||
|
||||
ret = spi_setup(spi);
|
||||
if (ret < 0) {
|
||||
dev_err(&spi->dev, "spi_setup failed: %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
tpo_td043 = kzalloc(sizeof(*tpo_td043), GFP_KERNEL);
|
||||
if (tpo_td043 == NULL)
|
||||
return -ENOMEM;
|
||||
|
||||
tpo_td043->spi = spi;
|
||||
dev_set_drvdata(&spi->dev, tpo_td043);
|
||||
dev_set_drvdata(&dssdev->dev, tpo_td043);
|
||||
|
||||
omap_dss_register_driver(&tpo_td043_driver);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int __devexit tpo_td043_spi_remove(struct spi_device *spi)
|
||||
{
|
||||
struct tpo_td043_device *tpo_td043 = dev_get_drvdata(&spi->dev);
|
||||
|
||||
omap_dss_unregister_driver(&tpo_td043_driver);
|
||||
kfree(tpo_td043);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct spi_driver tpo_td043_spi_driver = {
|
||||
.driver = {
|
||||
.name = "tpo_td043mtea1_panel_spi",
|
||||
.bus = &spi_bus_type,
|
||||
.owner = THIS_MODULE,
|
||||
},
|
||||
.probe = tpo_td043_spi_probe,
|
||||
.remove = __devexit_p(tpo_td043_spi_remove),
|
||||
};
|
||||
|
||||
static int __init tpo_td043_init(void)
|
||||
{
|
||||
return spi_register_driver(&tpo_td043_spi_driver);
|
||||
}
|
||||
|
||||
static void __exit tpo_td043_exit(void)
|
||||
{
|
||||
spi_unregister_driver(&tpo_td043_spi_driver);
|
||||
}
|
||||
|
||||
module_init(tpo_td043_init);
|
||||
module_exit(tpo_td043_exit);
|
||||
|
||||
MODULE_AUTHOR("Gražvydas Ignotas <notasas@gmail.com>");
|
||||
MODULE_DESCRIPTION("TPO TD043MTEA1 LCD Driver");
|
||||
MODULE_LICENSE("GPL");
|
|
@ -30,19 +30,29 @@ config OMAP2_DSS_COLLECT_IRQ_STATS
|
|||
depends on OMAP2_DSS_DEBUG_SUPPORT
|
||||
default n
|
||||
help
|
||||
Collect DSS IRQ statistics, printable via debugfs
|
||||
Collect DSS IRQ statistics, printable via debugfs.
|
||||
|
||||
The statistics can be found from
|
||||
<debugfs>/omapdss/dispc_irq for DISPC interrupts, and
|
||||
<debugfs>/omapdss/dsi_irq for DSI interrupts.
|
||||
|
||||
config OMAP2_DSS_RFBI
|
||||
bool "RFBI support"
|
||||
default n
|
||||
help
|
||||
MIPI DBI, or RFBI (Remote Framebuffer Interface), support.
|
||||
MIPI DBI support (RFBI, Remote Framebuffer Interface, in Texas
|
||||
Instrument's terminology).
|
||||
|
||||
DBI is a bus between the host processor and a peripheral,
|
||||
such as a display or a framebuffer chip.
|
||||
|
||||
See http://www.mipi.org/ for DBI spesifications.
|
||||
|
||||
config OMAP2_DSS_VENC
|
||||
bool "VENC support"
|
||||
default y
|
||||
help
|
||||
OMAP Video Encoder support.
|
||||
OMAP Video Encoder support for S-Video and composite TV-out.
|
||||
|
||||
config OMAP2_DSS_SDI
|
||||
bool "SDI support"
|
||||
|
@ -51,12 +61,20 @@ config OMAP2_DSS_SDI
|
|||
help
|
||||
SDI (Serial Display Interface) support.
|
||||
|
||||
SDI is a high speed one-way display serial bus between the host
|
||||
processor and a display.
|
||||
|
||||
config OMAP2_DSS_DSI
|
||||
bool "DSI support"
|
||||
depends on ARCH_OMAP3
|
||||
default n
|
||||
help
|
||||
MIPI DSI support.
|
||||
MIPI DSI (Display Serial Interface) support.
|
||||
|
||||
DSI is a high speed half-duplex serial interface between the host
|
||||
processor and a peripheral, such as a display or a framebuffer chip.
|
||||
|
||||
See http://www.mipi.org/ for DSI spesifications.
|
||||
|
||||
config OMAP2_DSS_USE_DSI_PLL
|
||||
bool "Use DSI PLL for PCLK (EXPERIMENTAL)"
|
||||
|
|
|
@ -31,6 +31,7 @@
|
|||
#include <linux/debugfs.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/device.h>
|
||||
#include <linux/regulator/consumer.h>
|
||||
|
||||
#include <plat/display.h>
|
||||
#include <plat/clock.h>
|
||||
|
@ -47,6 +48,10 @@ static struct {
|
|||
struct clk *dss_54m_fck;
|
||||
struct clk *dss_96m_fck;
|
||||
unsigned num_clks_enabled;
|
||||
|
||||
struct regulator *vdds_dsi_reg;
|
||||
struct regulator *vdds_sdi_reg;
|
||||
struct regulator *vdda_dac_reg;
|
||||
} core;
|
||||
|
||||
static void dss_clk_enable_all_no_ctx(void);
|
||||
|
@ -284,9 +289,11 @@ static void dss_clk_enable_no_ctx(enum dss_clock clks)
|
|||
|
||||
void dss_clk_enable(enum dss_clock clks)
|
||||
{
|
||||
bool check_ctx = core.num_clks_enabled == 0;
|
||||
|
||||
dss_clk_enable_no_ctx(clks);
|
||||
|
||||
if (cpu_is_omap34xx() && dss_need_ctx_restore())
|
||||
if (check_ctx && cpu_is_omap34xx() && dss_need_ctx_restore())
|
||||
restore_all_ctx();
|
||||
}
|
||||
|
||||
|
@ -352,6 +359,50 @@ static void dss_clk_disable_all(void)
|
|||
dss_clk_disable(clks);
|
||||
}
|
||||
|
||||
/* REGULATORS */
|
||||
|
||||
struct regulator *dss_get_vdds_dsi(void)
|
||||
{
|
||||
struct regulator *reg;
|
||||
|
||||
if (core.vdds_dsi_reg != NULL)
|
||||
return core.vdds_dsi_reg;
|
||||
|
||||
reg = regulator_get(&core.pdev->dev, "vdds_dsi");
|
||||
if (!IS_ERR(reg))
|
||||
core.vdds_dsi_reg = reg;
|
||||
|
||||
return reg;
|
||||
}
|
||||
|
||||
struct regulator *dss_get_vdds_sdi(void)
|
||||
{
|
||||
struct regulator *reg;
|
||||
|
||||
if (core.vdds_sdi_reg != NULL)
|
||||
return core.vdds_sdi_reg;
|
||||
|
||||
reg = regulator_get(&core.pdev->dev, "vdds_sdi");
|
||||
if (!IS_ERR(reg))
|
||||
core.vdds_sdi_reg = reg;
|
||||
|
||||
return reg;
|
||||
}
|
||||
|
||||
struct regulator *dss_get_vdda_dac(void)
|
||||
{
|
||||
struct regulator *reg;
|
||||
|
||||
if (core.vdda_dac_reg != NULL)
|
||||
return core.vdda_dac_reg;
|
||||
|
||||
reg = regulator_get(&core.pdev->dev, "vdda_dac");
|
||||
if (!IS_ERR(reg))
|
||||
core.vdda_dac_reg = reg;
|
||||
|
||||
return reg;
|
||||
}
|
||||
|
||||
/* DEBUGFS */
|
||||
#if defined(CONFIG_DEBUG_FS) && defined(CONFIG_OMAP2_DSS_DEBUG_SUPPORT)
|
||||
static void dss_debug_dump_clocks(struct seq_file *s)
|
||||
|
@ -397,10 +448,12 @@ static int dss_initialize_debugfs(void)
|
|||
debugfs_create_file("clk", S_IRUGO, dss_debugfs_dir,
|
||||
&dss_debug_dump_clocks, &dss_debug_fops);
|
||||
|
||||
#ifdef CONFIG_OMAP2_DSS_COLLECT_IRQ_STATS
|
||||
debugfs_create_file("dispc_irq", S_IRUGO, dss_debugfs_dir,
|
||||
&dispc_dump_irqs, &dss_debug_fops);
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_OMAP2_DSS_DSI
|
||||
#if defined(CONFIG_OMAP2_DSS_DSI) && defined(CONFIG_OMAP2_DSS_COLLECT_IRQ_STATS)
|
||||
debugfs_create_file("dsi_irq", S_IRUGO, dss_debugfs_dir,
|
||||
&dsi_dump_irqs, &dss_debug_fops);
|
||||
#endif
|
||||
|
@ -473,7 +526,7 @@ static int omap_dss_probe(struct platform_device *pdev)
|
|||
}
|
||||
#endif
|
||||
|
||||
r = dpi_init();
|
||||
r = dpi_init(pdev);
|
||||
if (r) {
|
||||
DSSERR("Failed to initialize dpi\n");
|
||||
goto fail0;
|
||||
|
@ -718,16 +771,14 @@ static int dss_driver_probe(struct device *dev)
|
|||
|
||||
dss_init_device(core.pdev, dssdev);
|
||||
|
||||
/* skip this if the device is behind a ctrl */
|
||||
if (!dssdev->panel.ctrl) {
|
||||
force = pdata->default_device == dssdev;
|
||||
dss_recheck_connections(dssdev, force);
|
||||
}
|
||||
force = pdata->default_device == dssdev;
|
||||
dss_recheck_connections(dssdev, force);
|
||||
|
||||
r = dssdrv->probe(dssdev);
|
||||
|
||||
if (r) {
|
||||
DSSERR("driver probe failed: %d\n", r);
|
||||
dss_uninit_device(core.pdev, dssdev);
|
||||
return r;
|
||||
}
|
||||
|
||||
|
@ -760,6 +811,13 @@ int omap_dss_register_driver(struct omap_dss_driver *dssdriver)
|
|||
dssdriver->driver.bus = &dss_bus_type;
|
||||
dssdriver->driver.probe = dss_driver_probe;
|
||||
dssdriver->driver.remove = dss_driver_remove;
|
||||
|
||||
if (dssdriver->get_resolution == NULL)
|
||||
dssdriver->get_resolution = omapdss_default_get_resolution;
|
||||
if (dssdriver->get_recommended_bpp == NULL)
|
||||
dssdriver->get_recommended_bpp =
|
||||
omapdss_default_get_recommended_bpp;
|
||||
|
||||
return driver_register(&dssdriver->driver);
|
||||
}
|
||||
EXPORT_SYMBOL(omap_dss_register_driver);
|
||||
|
@ -808,8 +866,6 @@ static void omap_dss_dev_release(struct device *dev)
|
|||
int omap_dss_register_device(struct omap_dss_device *dssdev)
|
||||
{
|
||||
static int dev_num;
|
||||
static int panel_num;
|
||||
int r;
|
||||
|
||||
WARN_ON(!dssdev->driver_name);
|
||||
|
||||
|
@ -818,36 +874,12 @@ int omap_dss_register_device(struct omap_dss_device *dssdev)
|
|||
dssdev->dev.parent = &dss_bus;
|
||||
dssdev->dev.release = omap_dss_dev_release;
|
||||
dev_set_name(&dssdev->dev, "display%d", dev_num++);
|
||||
r = device_register(&dssdev->dev);
|
||||
if (r)
|
||||
return r;
|
||||
|
||||
if (dssdev->ctrl.panel) {
|
||||
struct omap_dss_device *panel = dssdev->ctrl.panel;
|
||||
|
||||
panel->panel.ctrl = dssdev;
|
||||
|
||||
reset_device(&panel->dev, 1);
|
||||
panel->dev.bus = &dss_bus_type;
|
||||
panel->dev.parent = &dssdev->dev;
|
||||
panel->dev.release = omap_dss_dev_release;
|
||||
dev_set_name(&panel->dev, "panel%d", panel_num++);
|
||||
r = device_register(&panel->dev);
|
||||
if (r)
|
||||
return r;
|
||||
}
|
||||
|
||||
return 0;
|
||||
return device_register(&dssdev->dev);
|
||||
}
|
||||
|
||||
void omap_dss_unregister_device(struct omap_dss_device *dssdev)
|
||||
{
|
||||
device_unregister(&dssdev->dev);
|
||||
|
||||
if (dssdev->ctrl.panel) {
|
||||
struct omap_dss_device *panel = dssdev->ctrl.panel;
|
||||
device_unregister(&panel->dev);
|
||||
}
|
||||
}
|
||||
|
||||
/* BUS */
|
||||
|
@ -901,6 +933,21 @@ static int __init omap_dss_init(void)
|
|||
|
||||
static void __exit omap_dss_exit(void)
|
||||
{
|
||||
if (core.vdds_dsi_reg != NULL) {
|
||||
regulator_put(core.vdds_dsi_reg);
|
||||
core.vdds_dsi_reg = NULL;
|
||||
}
|
||||
|
||||
if (core.vdds_sdi_reg != NULL) {
|
||||
regulator_put(core.vdds_sdi_reg);
|
||||
core.vdds_sdi_reg = NULL;
|
||||
}
|
||||
|
||||
if (core.vdda_dac_reg != NULL) {
|
||||
regulator_put(core.vdda_dac_reg);
|
||||
core.vdda_dac_reg = NULL;
|
||||
}
|
||||
|
||||
platform_driver_unregister(&omap_dss_driver);
|
||||
|
||||
omap_dss_bus_unregister();
|
||||
|
|
|
@ -1725,7 +1725,7 @@ static void _enable_lcd_out(bool enable)
|
|||
REG_FLD_MOD(DISPC_CONTROL, enable ? 1 : 0, 0, 0);
|
||||
}
|
||||
|
||||
void dispc_enable_lcd_out(bool enable)
|
||||
static void dispc_enable_lcd_out(bool enable)
|
||||
{
|
||||
struct completion frame_done_completion;
|
||||
bool is_on;
|
||||
|
@ -1772,7 +1772,7 @@ static void _enable_digit_out(bool enable)
|
|||
REG_FLD_MOD(DISPC_CONTROL, enable ? 1 : 0, 1, 1);
|
||||
}
|
||||
|
||||
void dispc_enable_digit_out(bool enable)
|
||||
static void dispc_enable_digit_out(bool enable)
|
||||
{
|
||||
struct completion frame_done_completion;
|
||||
int r;
|
||||
|
@ -1836,6 +1836,26 @@ void dispc_enable_digit_out(bool enable)
|
|||
enable_clocks(0);
|
||||
}
|
||||
|
||||
bool dispc_is_channel_enabled(enum omap_channel channel)
|
||||
{
|
||||
if (channel == OMAP_DSS_CHANNEL_LCD)
|
||||
return !!REG_GET(DISPC_CONTROL, 0, 0);
|
||||
else if (channel == OMAP_DSS_CHANNEL_DIGIT)
|
||||
return !!REG_GET(DISPC_CONTROL, 1, 1);
|
||||
else
|
||||
BUG();
|
||||
}
|
||||
|
||||
void dispc_enable_channel(enum omap_channel channel, bool enable)
|
||||
{
|
||||
if (channel == OMAP_DSS_CHANNEL_LCD)
|
||||
dispc_enable_lcd_out(enable);
|
||||
else if (channel == OMAP_DSS_CHANNEL_DIGIT)
|
||||
dispc_enable_digit_out(enable);
|
||||
else
|
||||
BUG();
|
||||
}
|
||||
|
||||
void dispc_lcd_enable_signal_polarity(bool act_high)
|
||||
{
|
||||
enable_clocks(1);
|
||||
|
@ -2198,7 +2218,7 @@ unsigned long dispc_fclk_rate(void)
|
|||
{
|
||||
unsigned long r = 0;
|
||||
|
||||
if (dss_get_dispc_clk_source() == 0)
|
||||
if (dss_get_dispc_clk_source() == DSS_SRC_DSS1_ALWON_FCLK)
|
||||
r = dss_clk_get_rate(DSS_CLK_FCK1);
|
||||
else
|
||||
#ifdef CONFIG_OMAP2_DSS_DSI
|
||||
|
@ -2251,7 +2271,7 @@ void dispc_dump_clocks(struct seq_file *s)
|
|||
seq_printf(s, "- DISPC -\n");
|
||||
|
||||
seq_printf(s, "dispc fclk source = %s\n",
|
||||
dss_get_dispc_clk_source() == 0 ?
|
||||
dss_get_dispc_clk_source() == DSS_SRC_DSS1_ALWON_FCLK ?
|
||||
"dss1_alwon_fclk" : "dsi1_pll_fclk");
|
||||
|
||||
seq_printf(s, "fck\t\t%-16lu\n", dispc_fclk_rate());
|
||||
|
@ -2301,8 +2321,6 @@ void dispc_dump_irqs(struct seq_file *s)
|
|||
PIS(WAKEUP);
|
||||
#undef PIS
|
||||
}
|
||||
#else
|
||||
void dispc_dump_irqs(struct seq_file *s) { }
|
||||
#endif
|
||||
|
||||
void dispc_dump_regs(struct seq_file *s)
|
||||
|
@ -2854,12 +2872,13 @@ static void dispc_error_worker(struct work_struct *work)
|
|||
manager = mgr;
|
||||
enable = mgr->device->state ==
|
||||
OMAP_DSS_DISPLAY_ACTIVE;
|
||||
mgr->device->disable(mgr->device);
|
||||
mgr->device->driver->disable(mgr->device);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (manager) {
|
||||
struct omap_dss_device *dssdev = manager->device;
|
||||
for (i = 0; i < omap_dss_get_num_overlays(); ++i) {
|
||||
struct omap_overlay *ovl;
|
||||
ovl = omap_dss_get_overlay(i);
|
||||
|
@ -2874,7 +2893,7 @@ static void dispc_error_worker(struct work_struct *work)
|
|||
dispc_go(manager->id);
|
||||
mdelay(50);
|
||||
if (enable)
|
||||
manager->device->enable(manager->device);
|
||||
dssdev->driver->enable(dssdev);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2892,12 +2911,13 @@ static void dispc_error_worker(struct work_struct *work)
|
|||
manager = mgr;
|
||||
enable = mgr->device->state ==
|
||||
OMAP_DSS_DISPLAY_ACTIVE;
|
||||
mgr->device->disable(mgr->device);
|
||||
mgr->device->driver->disable(mgr->device);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (manager) {
|
||||
struct omap_dss_device *dssdev = manager->device;
|
||||
for (i = 0; i < omap_dss_get_num_overlays(); ++i) {
|
||||
struct omap_overlay *ovl;
|
||||
ovl = omap_dss_get_overlay(i);
|
||||
|
@ -2912,7 +2932,7 @@ static void dispc_error_worker(struct work_struct *work)
|
|||
dispc_go(manager->id);
|
||||
mdelay(50);
|
||||
if (enable)
|
||||
manager->device->enable(manager->device);
|
||||
dssdev->driver->enable(dssdev);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2923,7 +2943,7 @@ static void dispc_error_worker(struct work_struct *work)
|
|||
mgr = omap_dss_get_overlay_manager(i);
|
||||
|
||||
if (mgr->caps & OMAP_DSS_OVL_CAP_DISPC)
|
||||
mgr->device->disable(mgr->device);
|
||||
mgr->device->driver->disable(mgr->device);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -53,11 +53,11 @@ static ssize_t display_enabled_store(struct device *dev,
|
|||
|
||||
if (enabled != (dssdev->state != OMAP_DSS_DISPLAY_DISABLED)) {
|
||||
if (enabled) {
|
||||
r = dssdev->enable(dssdev);
|
||||
r = dssdev->driver->enable(dssdev);
|
||||
if (r)
|
||||
return r;
|
||||
} else {
|
||||
dssdev->disable(dssdev);
|
||||
dssdev->driver->disable(dssdev);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -69,8 +69,8 @@ static ssize_t display_upd_mode_show(struct device *dev,
|
|||
{
|
||||
struct omap_dss_device *dssdev = to_dss_device(dev);
|
||||
enum omap_dss_update_mode mode = OMAP_DSS_UPDATE_AUTO;
|
||||
if (dssdev->get_update_mode)
|
||||
mode = dssdev->get_update_mode(dssdev);
|
||||
if (dssdev->driver->get_update_mode)
|
||||
mode = dssdev->driver->get_update_mode(dssdev);
|
||||
return snprintf(buf, PAGE_SIZE, "%d\n", mode);
|
||||
}
|
||||
|
||||
|
@ -94,7 +94,7 @@ static ssize_t display_upd_mode_store(struct device *dev,
|
|||
return -EINVAL;
|
||||
}
|
||||
|
||||
r = dssdev->set_update_mode(dssdev, mode);
|
||||
r = dssdev->driver->set_update_mode(dssdev, mode);
|
||||
if (r)
|
||||
return r;
|
||||
|
||||
|
@ -106,7 +106,8 @@ static ssize_t display_tear_show(struct device *dev,
|
|||
{
|
||||
struct omap_dss_device *dssdev = to_dss_device(dev);
|
||||
return snprintf(buf, PAGE_SIZE, "%d\n",
|
||||
dssdev->get_te ? dssdev->get_te(dssdev) : 0);
|
||||
dssdev->driver->get_te ?
|
||||
dssdev->driver->get_te(dssdev) : 0);
|
||||
}
|
||||
|
||||
static ssize_t display_tear_store(struct device *dev,
|
||||
|
@ -116,12 +117,12 @@ static ssize_t display_tear_store(struct device *dev,
|
|||
unsigned long te;
|
||||
int r;
|
||||
|
||||
if (!dssdev->enable_te || !dssdev->get_te)
|
||||
if (!dssdev->driver->enable_te || !dssdev->driver->get_te)
|
||||
return -ENOENT;
|
||||
|
||||
te = simple_strtoul(buf, NULL, 0);
|
||||
|
||||
r = dssdev->enable_te(dssdev, te);
|
||||
r = dssdev->driver->enable_te(dssdev, te);
|
||||
if (r)
|
||||
return r;
|
||||
|
||||
|
@ -134,10 +135,10 @@ static ssize_t display_timings_show(struct device *dev,
|
|||
struct omap_dss_device *dssdev = to_dss_device(dev);
|
||||
struct omap_video_timings t;
|
||||
|
||||
if (!dssdev->get_timings)
|
||||
if (!dssdev->driver->get_timings)
|
||||
return -ENOENT;
|
||||
|
||||
dssdev->get_timings(dssdev, &t);
|
||||
dssdev->driver->get_timings(dssdev, &t);
|
||||
|
||||
return snprintf(buf, PAGE_SIZE, "%u,%u/%u/%u/%u,%u/%u/%u/%u\n",
|
||||
t.pixel_clock,
|
||||
|
@ -152,7 +153,7 @@ static ssize_t display_timings_store(struct device *dev,
|
|||
struct omap_video_timings t;
|
||||
int r, found;
|
||||
|
||||
if (!dssdev->set_timings || !dssdev->check_timings)
|
||||
if (!dssdev->driver->set_timings || !dssdev->driver->check_timings)
|
||||
return -ENOENT;
|
||||
|
||||
found = 0;
|
||||
|
@ -171,11 +172,11 @@ static ssize_t display_timings_store(struct device *dev,
|
|||
&t.y_res, &t.vfp, &t.vbp, &t.vsw) != 9)
|
||||
return -EINVAL;
|
||||
|
||||
r = dssdev->check_timings(dssdev, &t);
|
||||
r = dssdev->driver->check_timings(dssdev, &t);
|
||||
if (r)
|
||||
return r;
|
||||
|
||||
dssdev->set_timings(dssdev, &t);
|
||||
dssdev->driver->set_timings(dssdev, &t);
|
||||
|
||||
return size;
|
||||
}
|
||||
|
@ -185,9 +186,9 @@ static ssize_t display_rotate_show(struct device *dev,
|
|||
{
|
||||
struct omap_dss_device *dssdev = to_dss_device(dev);
|
||||
int rotate;
|
||||
if (!dssdev->get_rotate)
|
||||
if (!dssdev->driver->get_rotate)
|
||||
return -ENOENT;
|
||||
rotate = dssdev->get_rotate(dssdev);
|
||||
rotate = dssdev->driver->get_rotate(dssdev);
|
||||
return snprintf(buf, PAGE_SIZE, "%u\n", rotate);
|
||||
}
|
||||
|
||||
|
@ -198,12 +199,12 @@ static ssize_t display_rotate_store(struct device *dev,
|
|||
unsigned long rot;
|
||||
int r;
|
||||
|
||||
if (!dssdev->set_rotate || !dssdev->get_rotate)
|
||||
if (!dssdev->driver->set_rotate || !dssdev->driver->get_rotate)
|
||||
return -ENOENT;
|
||||
|
||||
rot = simple_strtoul(buf, NULL, 0);
|
||||
|
||||
r = dssdev->set_rotate(dssdev, rot);
|
||||
r = dssdev->driver->set_rotate(dssdev, rot);
|
||||
if (r)
|
||||
return r;
|
||||
|
||||
|
@ -215,9 +216,9 @@ static ssize_t display_mirror_show(struct device *dev,
|
|||
{
|
||||
struct omap_dss_device *dssdev = to_dss_device(dev);
|
||||
int mirror;
|
||||
if (!dssdev->get_mirror)
|
||||
if (!dssdev->driver->get_mirror)
|
||||
return -ENOENT;
|
||||
mirror = dssdev->get_mirror(dssdev);
|
||||
mirror = dssdev->driver->get_mirror(dssdev);
|
||||
return snprintf(buf, PAGE_SIZE, "%u\n", mirror);
|
||||
}
|
||||
|
||||
|
@ -228,12 +229,12 @@ static ssize_t display_mirror_store(struct device *dev,
|
|||
unsigned long mirror;
|
||||
int r;
|
||||
|
||||
if (!dssdev->set_mirror || !dssdev->get_mirror)
|
||||
if (!dssdev->driver->set_mirror || !dssdev->driver->get_mirror)
|
||||
return -ENOENT;
|
||||
|
||||
mirror = simple_strtoul(buf, NULL, 0);
|
||||
|
||||
r = dssdev->set_mirror(dssdev, mirror);
|
||||
r = dssdev->driver->set_mirror(dssdev, mirror);
|
||||
if (r)
|
||||
return r;
|
||||
|
||||
|
@ -246,10 +247,10 @@ static ssize_t display_wss_show(struct device *dev,
|
|||
struct omap_dss_device *dssdev = to_dss_device(dev);
|
||||
unsigned int wss;
|
||||
|
||||
if (!dssdev->get_wss)
|
||||
if (!dssdev->driver->get_wss)
|
||||
return -ENOENT;
|
||||
|
||||
wss = dssdev->get_wss(dssdev);
|
||||
wss = dssdev->driver->get_wss(dssdev);
|
||||
|
||||
return snprintf(buf, PAGE_SIZE, "0x%05x\n", wss);
|
||||
}
|
||||
|
@ -261,7 +262,7 @@ static ssize_t display_wss_store(struct device *dev,
|
|||
unsigned long wss;
|
||||
int r;
|
||||
|
||||
if (!dssdev->get_wss || !dssdev->set_wss)
|
||||
if (!dssdev->driver->get_wss || !dssdev->driver->set_wss)
|
||||
return -ENOENT;
|
||||
|
||||
if (strict_strtoul(buf, 0, &wss))
|
||||
|
@ -270,7 +271,7 @@ static ssize_t display_wss_store(struct device *dev,
|
|||
if (wss > 0xfffff)
|
||||
return -EINVAL;
|
||||
|
||||
r = dssdev->set_wss(dssdev, wss);
|
||||
r = dssdev->driver->set_wss(dssdev, wss);
|
||||
if (r)
|
||||
return r;
|
||||
|
||||
|
@ -303,12 +304,13 @@ static struct device_attribute *display_sysfs_attrs[] = {
|
|||
NULL
|
||||
};
|
||||
|
||||
static void default_get_resolution(struct omap_dss_device *dssdev,
|
||||
void omapdss_default_get_resolution(struct omap_dss_device *dssdev,
|
||||
u16 *xres, u16 *yres)
|
||||
{
|
||||
*xres = dssdev->panel.timings.x_res;
|
||||
*yres = dssdev->panel.timings.y_res;
|
||||
}
|
||||
EXPORT_SYMBOL(omapdss_default_get_resolution);
|
||||
|
||||
void default_get_overlay_fifo_thresholds(enum omap_plane plane,
|
||||
u32 fifo_size, enum omap_burst_size *burst_size,
|
||||
|
@ -323,24 +325,8 @@ void default_get_overlay_fifo_thresholds(enum omap_plane plane,
|
|||
*fifo_low = fifo_size - burst_size_bytes;
|
||||
}
|
||||
|
||||
static int default_wait_vsync(struct omap_dss_device *dssdev)
|
||||
int omapdss_default_get_recommended_bpp(struct omap_dss_device *dssdev)
|
||||
{
|
||||
unsigned long timeout = msecs_to_jiffies(500);
|
||||
u32 irq;
|
||||
|
||||
if (dssdev->type == OMAP_DISPLAY_TYPE_VENC)
|
||||
irq = DISPC_IRQ_EVSYNC_ODD;
|
||||
else
|
||||
irq = DISPC_IRQ_VSYNC;
|
||||
|
||||
return omap_dispc_wait_for_irq_interruptible_timeout(irq, timeout);
|
||||
}
|
||||
|
||||
static int default_get_recommended_bpp(struct omap_dss_device *dssdev)
|
||||
{
|
||||
if (dssdev->panel.recommended_bpp)
|
||||
return dssdev->panel.recommended_bpp;
|
||||
|
||||
switch (dssdev->type) {
|
||||
case OMAP_DISPLAY_TYPE_DPI:
|
||||
if (dssdev->phy.dpi.data_lines == 24)
|
||||
|
@ -362,6 +348,7 @@ static int default_get_recommended_bpp(struct omap_dss_device *dssdev)
|
|||
BUG();
|
||||
}
|
||||
}
|
||||
EXPORT_SYMBOL(omapdss_default_get_recommended_bpp);
|
||||
|
||||
/* Checks if replication logic should be used. Only use for active matrix,
|
||||
* when overlay is in RGB12U or RGB16 mode, and LCD interface is
|
||||
|
@ -425,10 +412,6 @@ void dss_init_device(struct platform_device *pdev,
|
|||
return;
|
||||
}
|
||||
|
||||
dssdev->get_resolution = default_get_resolution;
|
||||
dssdev->get_recommended_bpp = default_get_recommended_bpp;
|
||||
dssdev->wait_vsync = default_wait_vsync;
|
||||
|
||||
switch (dssdev->type) {
|
||||
case OMAP_DISPLAY_TYPE_DPI:
|
||||
r = dpi_init_display(dssdev);
|
||||
|
@ -502,13 +485,13 @@ static int dss_suspend_device(struct device *dev, void *data)
|
|||
return 0;
|
||||
}
|
||||
|
||||
if (!dssdev->suspend) {
|
||||
if (!dssdev->driver->suspend) {
|
||||
DSSERR("display '%s' doesn't implement suspend\n",
|
||||
dssdev->name);
|
||||
return -ENOSYS;
|
||||
}
|
||||
|
||||
r = dssdev->suspend(dssdev);
|
||||
r = dssdev->driver->suspend(dssdev);
|
||||
if (r)
|
||||
return r;
|
||||
|
||||
|
@ -537,8 +520,8 @@ static int dss_resume_device(struct device *dev, void *data)
|
|||
int r;
|
||||
struct omap_dss_device *dssdev = to_dss_device(dev);
|
||||
|
||||
if (dssdev->activate_after_resume && dssdev->resume) {
|
||||
r = dssdev->resume(dssdev);
|
||||
if (dssdev->activate_after_resume && dssdev->driver->resume) {
|
||||
r = dssdev->driver->resume(dssdev);
|
||||
if (r)
|
||||
return r;
|
||||
}
|
||||
|
@ -558,7 +541,7 @@ int dss_resume_all_devices(void)
|
|||
static int dss_disable_device(struct device *dev, void *data)
|
||||
{
|
||||
struct omap_dss_device *dssdev = to_dss_device(dev);
|
||||
dssdev->disable(dssdev);
|
||||
dssdev->driver->disable(dssdev);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -591,10 +574,6 @@ struct omap_dss_device *omap_dss_get_next_device(struct omap_dss_device *from)
|
|||
|
||||
int match(struct device *dev, void *data)
|
||||
{
|
||||
/* skip panels connected to controllers */
|
||||
if (to_dss_device(dev)->panel.ctrl)
|
||||
return 0;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
@ -626,45 +605,21 @@ EXPORT_SYMBOL(omap_dss_find_device);
|
|||
|
||||
int omap_dss_start_device(struct omap_dss_device *dssdev)
|
||||
{
|
||||
int r;
|
||||
|
||||
if (!dssdev->driver) {
|
||||
DSSDBG("no driver\n");
|
||||
r = -ENODEV;
|
||||
goto err0;
|
||||
}
|
||||
|
||||
if (dssdev->ctrl.panel && !dssdev->ctrl.panel->driver) {
|
||||
DSSDBG("no panel driver\n");
|
||||
r = -ENODEV;
|
||||
goto err0;
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
if (!try_module_get(dssdev->dev.driver->owner)) {
|
||||
r = -ENODEV;
|
||||
goto err0;
|
||||
}
|
||||
|
||||
if (dssdev->ctrl.panel) {
|
||||
if (!try_module_get(dssdev->ctrl.panel->dev.driver->owner)) {
|
||||
r = -ENODEV;
|
||||
goto err1;
|
||||
}
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
return 0;
|
||||
err1:
|
||||
module_put(dssdev->dev.driver->owner);
|
||||
err0:
|
||||
return r;
|
||||
}
|
||||
EXPORT_SYMBOL(omap_dss_start_device);
|
||||
|
||||
void omap_dss_stop_device(struct omap_dss_device *dssdev)
|
||||
{
|
||||
if (dssdev->ctrl.panel)
|
||||
module_put(dssdev->ctrl.panel->dev.driver->owner);
|
||||
|
||||
module_put(dssdev->dev.driver->owner);
|
||||
}
|
||||
EXPORT_SYMBOL(omap_dss_stop_device);
|
||||
|
|
|
@ -25,7 +25,10 @@
|
|||
#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>
|
||||
|
@ -33,7 +36,7 @@
|
|||
#include "dss.h"
|
||||
|
||||
static struct {
|
||||
int update_enabled;
|
||||
struct regulator *vdds_dsi_reg;
|
||||
} dpi;
|
||||
|
||||
#ifdef CONFIG_OMAP2_DSS_USE_DSI_PLL
|
||||
|
@ -53,7 +56,7 @@ static int dpi_set_dsi_clk(bool is_tft, unsigned long pck_req,
|
|||
if (r)
|
||||
return r;
|
||||
|
||||
dss_select_clk_source(0, 1);
|
||||
dss_select_dispc_clk_source(DSS_SRC_DSI1_PLL_FCLK);
|
||||
|
||||
r = dispc_set_clock_div(&dispc_cinfo);
|
||||
if (r)
|
||||
|
@ -150,7 +153,7 @@ static int dpi_basic_init(struct omap_dss_device *dssdev)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int dpi_display_enable(struct omap_dss_device *dssdev)
|
||||
int omapdss_dpi_display_enable(struct omap_dss_device *dssdev)
|
||||
{
|
||||
int r;
|
||||
|
||||
|
@ -160,10 +163,10 @@ static int dpi_display_enable(struct omap_dss_device *dssdev)
|
|||
goto err0;
|
||||
}
|
||||
|
||||
if (dssdev->state != OMAP_DSS_DISPLAY_DISABLED) {
|
||||
DSSERR("display already enabled\n");
|
||||
r = -EINVAL;
|
||||
goto err1;
|
||||
if (cpu_is_omap34xx()) {
|
||||
r = regulator_enable(dpi.vdds_dsi_reg);
|
||||
if (r)
|
||||
goto err1;
|
||||
}
|
||||
|
||||
dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK1);
|
||||
|
@ -184,18 +187,10 @@ static int dpi_display_enable(struct omap_dss_device *dssdev)
|
|||
|
||||
mdelay(2);
|
||||
|
||||
dispc_enable_lcd_out(1);
|
||||
|
||||
r = dssdev->driver->enable(dssdev);
|
||||
if (r)
|
||||
goto err5;
|
||||
|
||||
dssdev->state = OMAP_DSS_DISPLAY_ACTIVE;
|
||||
dssdev->manager->enable(dssdev->manager);
|
||||
|
||||
return 0;
|
||||
|
||||
err5:
|
||||
dispc_enable_lcd_out(0);
|
||||
err4:
|
||||
#ifdef CONFIG_OMAP2_DSS_USE_DSI_PLL
|
||||
dsi_pll_uninit();
|
||||
|
@ -204,78 +199,35 @@ err3:
|
|||
#endif
|
||||
err2:
|
||||
dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK1);
|
||||
if (cpu_is_omap34xx())
|
||||
regulator_disable(dpi.vdds_dsi_reg);
|
||||
err1:
|
||||
omap_dss_stop_device(dssdev);
|
||||
err0:
|
||||
return r;
|
||||
}
|
||||
EXPORT_SYMBOL(omapdss_dpi_display_enable);
|
||||
|
||||
static int dpi_display_resume(struct omap_dss_device *dssdev);
|
||||
|
||||
static void dpi_display_disable(struct omap_dss_device *dssdev)
|
||||
void omapdss_dpi_display_disable(struct omap_dss_device *dssdev)
|
||||
{
|
||||
if (dssdev->state == OMAP_DSS_DISPLAY_DISABLED)
|
||||
return;
|
||||
|
||||
if (dssdev->state == OMAP_DSS_DISPLAY_SUSPENDED)
|
||||
dpi_display_resume(dssdev);
|
||||
|
||||
dssdev->driver->disable(dssdev);
|
||||
|
||||
dispc_enable_lcd_out(0);
|
||||
dssdev->manager->disable(dssdev->manager);
|
||||
|
||||
#ifdef CONFIG_OMAP2_DSS_USE_DSI_PLL
|
||||
dss_select_clk_source(0, 0);
|
||||
dss_select_dispc_clk_source(DSS_SRC_DSS1_ALWON_FCLK);
|
||||
dsi_pll_uninit();
|
||||
dss_clk_disable(DSS_CLK_FCK2);
|
||||
#endif
|
||||
|
||||
dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK1);
|
||||
|
||||
dssdev->state = OMAP_DSS_DISPLAY_DISABLED;
|
||||
if (cpu_is_omap34xx())
|
||||
regulator_disable(dpi.vdds_dsi_reg);
|
||||
|
||||
omap_dss_stop_device(dssdev);
|
||||
}
|
||||
EXPORT_SYMBOL(omapdss_dpi_display_disable);
|
||||
|
||||
static int dpi_display_suspend(struct omap_dss_device *dssdev)
|
||||
{
|
||||
if (dssdev->state != OMAP_DSS_DISPLAY_ACTIVE)
|
||||
return -EINVAL;
|
||||
|
||||
DSSDBG("dpi_display_suspend\n");
|
||||
|
||||
if (dssdev->driver->suspend)
|
||||
dssdev->driver->suspend(dssdev);
|
||||
|
||||
dispc_enable_lcd_out(0);
|
||||
|
||||
dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK1);
|
||||
|
||||
dssdev->state = OMAP_DSS_DISPLAY_SUSPENDED;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int dpi_display_resume(struct omap_dss_device *dssdev)
|
||||
{
|
||||
if (dssdev->state != OMAP_DSS_DISPLAY_SUSPENDED)
|
||||
return -EINVAL;
|
||||
|
||||
DSSDBG("dpi_display_resume\n");
|
||||
|
||||
dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK1);
|
||||
|
||||
dispc_enable_lcd_out(1);
|
||||
|
||||
if (dssdev->driver->resume)
|
||||
dssdev->driver->resume(dssdev);
|
||||
|
||||
dssdev->state = OMAP_DSS_DISPLAY_ACTIVE;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void dpi_set_timings(struct omap_dss_device *dssdev,
|
||||
void dpi_set_timings(struct omap_dss_device *dssdev,
|
||||
struct omap_video_timings *timings)
|
||||
{
|
||||
DSSDBG("dpi_set_timings\n");
|
||||
|
@ -285,8 +237,9 @@ static void dpi_set_timings(struct omap_dss_device *dssdev,
|
|||
dispc_go(OMAP_DSS_CHANNEL_LCD);
|
||||
}
|
||||
}
|
||||
EXPORT_SYMBOL(dpi_set_timings);
|
||||
|
||||
static int dpi_check_timings(struct omap_dss_device *dssdev,
|
||||
int dpi_check_timings(struct omap_dss_device *dssdev,
|
||||
struct omap_video_timings *timings)
|
||||
{
|
||||
bool is_tft;
|
||||
|
@ -340,56 +293,25 @@ static int dpi_check_timings(struct omap_dss_device *dssdev,
|
|||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void dpi_get_timings(struct omap_dss_device *dssdev,
|
||||
struct omap_video_timings *timings)
|
||||
{
|
||||
*timings = dssdev->panel.timings;
|
||||
}
|
||||
|
||||
static int dpi_display_set_update_mode(struct omap_dss_device *dssdev,
|
||||
enum omap_dss_update_mode mode)
|
||||
{
|
||||
if (mode == OMAP_DSS_UPDATE_MANUAL)
|
||||
return -EINVAL;
|
||||
|
||||
if (mode == OMAP_DSS_UPDATE_DISABLED) {
|
||||
dispc_enable_lcd_out(0);
|
||||
dpi.update_enabled = 0;
|
||||
} else {
|
||||
dispc_enable_lcd_out(1);
|
||||
dpi.update_enabled = 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static enum omap_dss_update_mode dpi_display_get_update_mode(
|
||||
struct omap_dss_device *dssdev)
|
||||
{
|
||||
return dpi.update_enabled ? OMAP_DSS_UPDATE_AUTO :
|
||||
OMAP_DSS_UPDATE_DISABLED;
|
||||
}
|
||||
EXPORT_SYMBOL(dpi_check_timings);
|
||||
|
||||
int dpi_init_display(struct omap_dss_device *dssdev)
|
||||
{
|
||||
DSSDBG("init_display\n");
|
||||
|
||||
dssdev->enable = dpi_display_enable;
|
||||
dssdev->disable = dpi_display_disable;
|
||||
dssdev->suspend = dpi_display_suspend;
|
||||
dssdev->resume = dpi_display_resume;
|
||||
dssdev->set_timings = dpi_set_timings;
|
||||
dssdev->check_timings = dpi_check_timings;
|
||||
dssdev->get_timings = dpi_get_timings;
|
||||
dssdev->set_update_mode = dpi_display_set_update_mode;
|
||||
dssdev->get_update_mode = dpi_display_get_update_mode;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int dpi_init(void)
|
||||
int dpi_init(struct platform_device *pdev)
|
||||
{
|
||||
if (cpu_is_omap34xx()) {
|
||||
dpi.vdds_dsi_reg = dss_get_vdds_dsi();
|
||||
if (IS_ERR(dpi.vdds_dsi_reg)) {
|
||||
DSSERR("can't get VDDS_DSI regulator\n");
|
||||
return PTR_ERR(dpi.vdds_dsi_reg);
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
|
@ -68,6 +68,9 @@ static struct {
|
|||
struct dss_clock_info cache_dss_cinfo;
|
||||
struct dispc_clock_info cache_dispc_cinfo;
|
||||
|
||||
enum dss_clk_source dsi_clk_source;
|
||||
enum dss_clk_source dispc_clk_source;
|
||||
|
||||
u32 ctx[DSS_SZ_REGS / sizeof(u32)];
|
||||
} dss;
|
||||
|
||||
|
@ -247,23 +250,42 @@ void dss_dump_regs(struct seq_file *s)
|
|||
#undef DUMPREG
|
||||
}
|
||||
|
||||
void dss_select_clk_source(bool dsi, bool dispc)
|
||||
void dss_select_dispc_clk_source(enum dss_clk_source clk_src)
|
||||
{
|
||||
u32 r;
|
||||
r = dss_read_reg(DSS_CONTROL);
|
||||
r = FLD_MOD(r, dsi, 1, 1); /* DSI_CLK_SWITCH */
|
||||
r = FLD_MOD(r, dispc, 0, 0); /* DISPC_CLK_SWITCH */
|
||||
dss_write_reg(DSS_CONTROL, r);
|
||||
int b;
|
||||
|
||||
BUG_ON(clk_src != DSS_SRC_DSI1_PLL_FCLK &&
|
||||
clk_src != DSS_SRC_DSS1_ALWON_FCLK);
|
||||
|
||||
b = clk_src == DSS_SRC_DSS1_ALWON_FCLK ? 0 : 1;
|
||||
|
||||
REG_FLD_MOD(DSS_CONTROL, b, 0, 0); /* DISPC_CLK_SWITCH */
|
||||
|
||||
dss.dispc_clk_source = clk_src;
|
||||
}
|
||||
|
||||
int dss_get_dsi_clk_source(void)
|
||||
void dss_select_dsi_clk_source(enum dss_clk_source clk_src)
|
||||
{
|
||||
return FLD_GET(dss_read_reg(DSS_CONTROL), 1, 1);
|
||||
int b;
|
||||
|
||||
BUG_ON(clk_src != DSS_SRC_DSI2_PLL_FCLK &&
|
||||
clk_src != DSS_SRC_DSS1_ALWON_FCLK);
|
||||
|
||||
b = clk_src == DSS_SRC_DSS1_ALWON_FCLK ? 0 : 1;
|
||||
|
||||
REG_FLD_MOD(DSS_CONTROL, b, 1, 1); /* DSI_CLK_SWITCH */
|
||||
|
||||
dss.dsi_clk_source = clk_src;
|
||||
}
|
||||
|
||||
int dss_get_dispc_clk_source(void)
|
||||
enum dss_clk_source dss_get_dispc_clk_source(void)
|
||||
{
|
||||
return FLD_GET(dss_read_reg(DSS_CONTROL), 0, 0);
|
||||
return dss.dispc_clk_source;
|
||||
}
|
||||
|
||||
enum dss_clk_source dss_get_dsi_clk_source(void)
|
||||
{
|
||||
return dss.dsi_clk_source;
|
||||
}
|
||||
|
||||
/* calculate clock rates using dividers in cinfo */
|
||||
|
|
|
@ -119,6 +119,12 @@ enum dss_clock {
|
|||
DSS_CLK_96M = 1 << 4,
|
||||
};
|
||||
|
||||
enum dss_clk_source {
|
||||
DSS_SRC_DSI1_PLL_FCLK,
|
||||
DSS_SRC_DSI2_PLL_FCLK,
|
||||
DSS_SRC_DSS1_ALWON_FCLK,
|
||||
};
|
||||
|
||||
struct dss_clock_info {
|
||||
/* rates that we get with dividers below */
|
||||
unsigned long fck;
|
||||
|
@ -169,6 +175,9 @@ unsigned long dss_clk_get_rate(enum dss_clock clk);
|
|||
int dss_need_ctx_restore(void);
|
||||
void dss_dump_clocks(struct seq_file *s);
|
||||
struct bus_type *dss_get_bus(void);
|
||||
struct regulator *dss_get_vdds_dsi(void);
|
||||
struct regulator *dss_get_vdds_sdi(void);
|
||||
struct regulator *dss_get_vdda_dac(void);
|
||||
|
||||
/* display */
|
||||
int dss_suspend_all_devices(void);
|
||||
|
@ -216,9 +225,11 @@ void dss_sdi_init(u8 datapairs);
|
|||
int dss_sdi_enable(void);
|
||||
void dss_sdi_disable(void);
|
||||
|
||||
void dss_select_clk_source(bool dsi, bool dispc);
|
||||
int dss_get_dsi_clk_source(void);
|
||||
int dss_get_dispc_clk_source(void);
|
||||
void dss_select_dispc_clk_source(enum dss_clk_source clk_src);
|
||||
void dss_select_dsi_clk_source(enum dss_clk_source clk_src);
|
||||
enum dss_clk_source dss_get_dispc_clk_source(void);
|
||||
enum dss_clk_source dss_get_dsi_clk_source(void);
|
||||
|
||||
void dss_set_venc_output(enum omap_dss_venc_type type);
|
||||
void dss_set_dac_pwrdn_bgz(bool enable);
|
||||
|
||||
|
@ -261,7 +272,7 @@ void dsi_get_overlay_fifo_thresholds(enum omap_plane plane,
|
|||
u32 *fifo_low, u32 *fifo_high);
|
||||
|
||||
/* DPI */
|
||||
int dpi_init(void);
|
||||
int dpi_init(struct platform_device *pdev);
|
||||
void dpi_exit(void);
|
||||
int dpi_init_display(struct omap_dss_device *dssdev);
|
||||
|
||||
|
@ -313,8 +324,8 @@ int dispc_setup_plane(enum omap_plane plane,
|
|||
|
||||
bool dispc_go_busy(enum omap_channel channel);
|
||||
void dispc_go(enum omap_channel channel);
|
||||
void dispc_enable_lcd_out(bool enable);
|
||||
void dispc_enable_digit_out(bool enable);
|
||||
void dispc_enable_channel(enum omap_channel channel, bool enable);
|
||||
bool dispc_is_channel_enabled(enum omap_channel channel);
|
||||
int dispc_enable_plane(enum omap_plane plane, bool enable);
|
||||
void dispc_enable_replication(enum omap_plane plane, bool enable);
|
||||
|
||||
|
|
|
@ -501,6 +501,19 @@ static int omap_dss_unset_device(struct omap_overlay_manager *mgr)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int dss_mgr_wait_for_vsync(struct omap_overlay_manager *mgr)
|
||||
{
|
||||
unsigned long timeout = msecs_to_jiffies(500);
|
||||
u32 irq;
|
||||
|
||||
if (mgr->device->type == OMAP_DISPLAY_TYPE_VENC)
|
||||
irq = DISPC_IRQ_EVSYNC_ODD;
|
||||
else
|
||||
irq = DISPC_IRQ_VSYNC;
|
||||
|
||||
return omap_dispc_wait_for_irq_interruptible_timeout(irq, timeout);
|
||||
}
|
||||
|
||||
static int dss_mgr_wait_for_go(struct omap_overlay_manager *mgr)
|
||||
{
|
||||
unsigned long timeout = msecs_to_jiffies(500);
|
||||
|
@ -509,17 +522,18 @@ static int dss_mgr_wait_for_go(struct omap_overlay_manager *mgr)
|
|||
u32 irq;
|
||||
int r;
|
||||
int i;
|
||||
struct omap_dss_device *dssdev = mgr->device;
|
||||
|
||||
if (!mgr->device)
|
||||
if (!dssdev)
|
||||
return 0;
|
||||
|
||||
if (mgr->device->type == OMAP_DISPLAY_TYPE_VENC) {
|
||||
if (dssdev->type == OMAP_DISPLAY_TYPE_VENC) {
|
||||
irq = DISPC_IRQ_EVSYNC_ODD | DISPC_IRQ_EVSYNC_EVEN;
|
||||
channel = OMAP_DSS_CHANNEL_DIGIT;
|
||||
} else {
|
||||
if (mgr->device->caps & OMAP_DSS_DISPLAY_CAP_MANUAL_UPDATE) {
|
||||
if (dssdev->caps & OMAP_DSS_DISPLAY_CAP_MANUAL_UPDATE) {
|
||||
enum omap_dss_update_mode mode;
|
||||
mode = mgr->device->get_update_mode(mgr->device);
|
||||
mode = dssdev->driver->get_update_mode(dssdev);
|
||||
if (mode != OMAP_DSS_UPDATE_AUTO)
|
||||
return 0;
|
||||
|
||||
|
@ -592,7 +606,7 @@ int dss_mgr_wait_for_go_ovl(struct omap_overlay *ovl)
|
|||
} else {
|
||||
if (dssdev->caps & OMAP_DSS_DISPLAY_CAP_MANUAL_UPDATE) {
|
||||
enum omap_dss_update_mode mode;
|
||||
mode = dssdev->get_update_mode(dssdev);
|
||||
mode = dssdev->driver->get_update_mode(dssdev);
|
||||
if (mode != OMAP_DSS_UPDATE_AUTO)
|
||||
return 0;
|
||||
|
||||
|
@ -1064,7 +1078,7 @@ void dss_start_update(struct omap_dss_device *dssdev)
|
|||
mc->shadow_dirty = false;
|
||||
}
|
||||
|
||||
dispc_enable_lcd_out(1);
|
||||
dssdev->manager->enable(dssdev->manager);
|
||||
}
|
||||
|
||||
static void dss_apply_irq_handler(void *data, u32 mask)
|
||||
|
@ -1196,7 +1210,8 @@ static int omap_dss_mgr_apply(struct omap_overlay_manager *mgr)
|
|||
|
||||
oc->manual_update =
|
||||
dssdev->caps & OMAP_DSS_DISPLAY_CAP_MANUAL_UPDATE &&
|
||||
dssdev->get_update_mode(dssdev) != OMAP_DSS_UPDATE_AUTO;
|
||||
dssdev->driver->get_update_mode(dssdev) !=
|
||||
OMAP_DSS_UPDATE_AUTO;
|
||||
|
||||
++num_planes_enabled;
|
||||
}
|
||||
|
@ -1237,7 +1252,8 @@ static int omap_dss_mgr_apply(struct omap_overlay_manager *mgr)
|
|||
|
||||
mc->manual_update =
|
||||
dssdev->caps & OMAP_DSS_DISPLAY_CAP_MANUAL_UPDATE &&
|
||||
dssdev->get_update_mode(dssdev) != OMAP_DSS_UPDATE_AUTO;
|
||||
dssdev->driver->get_update_mode(dssdev) !=
|
||||
OMAP_DSS_UPDATE_AUTO;
|
||||
}
|
||||
|
||||
/* XXX TODO: Try to get fifomerge working. The problem is that it
|
||||
|
@ -1351,6 +1367,18 @@ static void omap_dss_mgr_get_info(struct omap_overlay_manager *mgr,
|
|||
*info = mgr->info;
|
||||
}
|
||||
|
||||
static int dss_mgr_enable(struct omap_overlay_manager *mgr)
|
||||
{
|
||||
dispc_enable_channel(mgr->id, 1);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int dss_mgr_disable(struct omap_overlay_manager *mgr)
|
||||
{
|
||||
dispc_enable_channel(mgr->id, 0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void omap_dss_add_overlay_manager(struct omap_overlay_manager *manager)
|
||||
{
|
||||
++num_managers;
|
||||
|
@ -1394,6 +1422,10 @@ int dss_init_overlay_managers(struct platform_device *pdev)
|
|||
mgr->set_manager_info = &omap_dss_mgr_set_info;
|
||||
mgr->get_manager_info = &omap_dss_mgr_get_info;
|
||||
mgr->wait_for_go = &dss_mgr_wait_for_go;
|
||||
mgr->wait_for_vsync = &dss_mgr_wait_for_vsync;
|
||||
|
||||
mgr->enable = &dss_mgr_enable;
|
||||
mgr->disable = &dss_mgr_disable;
|
||||
|
||||
mgr->caps = OMAP_DSS_OVL_MGR_CAP_DISPC;
|
||||
|
||||
|
|
|
@ -350,7 +350,7 @@ int dss_check_overlay(struct omap_overlay *ovl, struct omap_dss_device *dssdev)
|
|||
return -EINVAL;
|
||||
}
|
||||
|
||||
dssdev->get_resolution(dssdev, &dw, &dh);
|
||||
dssdev->driver->get_resolution(dssdev, &dw, &dh);
|
||||
|
||||
DSSDBG("check_overlay %d: (%d,%d %dx%d -> %dx%d) disp (%dx%d)\n",
|
||||
ovl->id,
|
||||
|
|
|
@ -36,8 +36,6 @@
|
|||
#include <plat/display.h>
|
||||
#include "dss.h"
|
||||
|
||||
/*#define MEASURE_PERF*/
|
||||
|
||||
#define RFBI_BASE 0x48050800
|
||||
|
||||
struct rfbi_reg { u16 idx; };
|
||||
|
@ -66,8 +64,6 @@ struct rfbi_reg { u16 idx; };
|
|||
#define RFBI_VSYNC_WIDTH RFBI_REG(0x0090)
|
||||
#define RFBI_HSYNC_WIDTH RFBI_REG(0x0094)
|
||||
|
||||
#define RFBI_CMD_FIFO_LEN_BYTES (16 * sizeof(struct update_param))
|
||||
|
||||
#define REG_FLD_MOD(idx, val, start, end) \
|
||||
rfbi_write_reg(idx, FLD_MOD(rfbi_read_reg(idx), val, start, end))
|
||||
|
||||
|
@ -102,7 +98,6 @@ enum update_cmd {
|
|||
|
||||
static int rfbi_convert_timings(struct rfbi_timings *t);
|
||||
static void rfbi_get_clk_info(u32 *clk_period, u32 *max_clk_div);
|
||||
static void process_cmd_fifo(void);
|
||||
|
||||
static struct {
|
||||
void __iomem *base;
|
||||
|
@ -125,11 +120,6 @@ static struct {
|
|||
struct completion cmd_done;
|
||||
atomic_t cmd_fifo_full;
|
||||
atomic_t cmd_pending;
|
||||
#ifdef MEASURE_PERF
|
||||
unsigned perf_bytes;
|
||||
ktime_t perf_setup_time;
|
||||
ktime_t perf_start_time;
|
||||
#endif
|
||||
} rfbi;
|
||||
|
||||
struct update_region {
|
||||
|
@ -139,16 +129,6 @@ struct update_region {
|
|||
u16 h;
|
||||
};
|
||||
|
||||
struct update_param {
|
||||
u8 rfbi_module;
|
||||
u8 cmd;
|
||||
|
||||
union {
|
||||
struct update_region r;
|
||||
struct completion *sync;
|
||||
} par;
|
||||
};
|
||||
|
||||
static inline void rfbi_write_reg(const struct rfbi_reg idx, u32 val)
|
||||
{
|
||||
__raw_writel(val, rfbi.base + idx.idx);
|
||||
|
@ -321,55 +301,6 @@ void omap_rfbi_write_pixels(const void __iomem *buf, int scr_width,
|
|||
}
|
||||
EXPORT_SYMBOL(omap_rfbi_write_pixels);
|
||||
|
||||
#ifdef MEASURE_PERF
|
||||
static void perf_mark_setup(void)
|
||||
{
|
||||
rfbi.perf_setup_time = ktime_get();
|
||||
}
|
||||
|
||||
static void perf_mark_start(void)
|
||||
{
|
||||
rfbi.perf_start_time = ktime_get();
|
||||
}
|
||||
|
||||
static void perf_show(const char *name)
|
||||
{
|
||||
ktime_t t, setup_time, trans_time;
|
||||
u32 total_bytes;
|
||||
u32 setup_us, trans_us, total_us;
|
||||
|
||||
t = ktime_get();
|
||||
|
||||
setup_time = ktime_sub(rfbi.perf_start_time, rfbi.perf_setup_time);
|
||||
setup_us = (u32)ktime_to_us(setup_time);
|
||||
if (setup_us == 0)
|
||||
setup_us = 1;
|
||||
|
||||
trans_time = ktime_sub(t, rfbi.perf_start_time);
|
||||
trans_us = (u32)ktime_to_us(trans_time);
|
||||
if (trans_us == 0)
|
||||
trans_us = 1;
|
||||
|
||||
total_us = setup_us + trans_us;
|
||||
|
||||
total_bytes = rfbi.perf_bytes;
|
||||
|
||||
DSSINFO("%s update %u us + %u us = %u us (%uHz), %u bytes, "
|
||||
"%u kbytes/sec\n",
|
||||
name,
|
||||
setup_us,
|
||||
trans_us,
|
||||
total_us,
|
||||
1000*1000 / total_us,
|
||||
total_bytes,
|
||||
total_bytes * 1000 / total_us);
|
||||
}
|
||||
#else
|
||||
#define perf_mark_setup()
|
||||
#define perf_mark_start()
|
||||
#define perf_show(x)
|
||||
#endif
|
||||
|
||||
void rfbi_transfer_area(u16 width, u16 height,
|
||||
void (callback)(void *data), void *data)
|
||||
{
|
||||
|
@ -382,7 +313,7 @@ void rfbi_transfer_area(u16 width, u16 height,
|
|||
|
||||
dispc_set_lcd_size(width, height);
|
||||
|
||||
dispc_enable_lcd_out(1);
|
||||
dispc_enable_channel(OMAP_DSS_CHANNEL_LCD, true);
|
||||
|
||||
rfbi.framedone_callback = callback;
|
||||
rfbi.framedone_callback_data = data;
|
||||
|
@ -396,8 +327,6 @@ void rfbi_transfer_area(u16 width, u16 height,
|
|||
if (!rfbi.te_enabled)
|
||||
l = FLD_MOD(l, 1, 4, 4); /* ITE */
|
||||
|
||||
perf_mark_start();
|
||||
|
||||
rfbi_write_reg(RFBI_CONTROL, l);
|
||||
}
|
||||
|
||||
|
@ -407,8 +336,6 @@ static void framedone_callback(void *data, u32 mask)
|
|||
|
||||
DSSDBG("FRAMEDONE\n");
|
||||
|
||||
perf_show("DISPC");
|
||||
|
||||
REG_FLD_MOD(RFBI_CONTROL, 0, 0, 0);
|
||||
|
||||
rfbi_enable_clocks(0);
|
||||
|
@ -416,11 +343,10 @@ static void framedone_callback(void *data, u32 mask)
|
|||
callback = rfbi.framedone_callback;
|
||||
rfbi.framedone_callback = NULL;
|
||||
|
||||
/*callback(rfbi.framedone_callback_data);*/
|
||||
if (callback != NULL)
|
||||
callback(rfbi.framedone_callback_data);
|
||||
|
||||
atomic_set(&rfbi.cmd_pending, 0);
|
||||
|
||||
process_cmd_fifo();
|
||||
}
|
||||
|
||||
#if 1 /* VERBOSE */
|
||||
|
@ -937,52 +863,43 @@ int rfbi_configure(int rfbi_module, int bpp, int lines)
|
|||
}
|
||||
EXPORT_SYMBOL(rfbi_configure);
|
||||
|
||||
static int rfbi_find_display(struct omap_dss_device *dssdev)
|
||||
int omap_rfbi_prepare_update(struct omap_dss_device *dssdev,
|
||||
u16 *x, u16 *y, u16 *w, u16 *h)
|
||||
{
|
||||
if (dssdev == rfbi.dssdev[0])
|
||||
return 0;
|
||||
u16 dw, dh;
|
||||
|
||||
if (dssdev == rfbi.dssdev[1])
|
||||
return 1;
|
||||
dssdev->driver->get_resolution(dssdev, &dw, &dh);
|
||||
|
||||
BUG();
|
||||
return -1;
|
||||
}
|
||||
if (*x > dw || *y > dh)
|
||||
return -EINVAL;
|
||||
|
||||
if (*x + *w > dw)
|
||||
return -EINVAL;
|
||||
|
||||
static void signal_fifo_waiters(void)
|
||||
{
|
||||
if (atomic_read(&rfbi.cmd_fifo_full) > 0) {
|
||||
/* DSSDBG("SIGNALING: Fifo not full for waiter!\n"); */
|
||||
complete(&rfbi.cmd_done);
|
||||
atomic_dec(&rfbi.cmd_fifo_full);
|
||||
}
|
||||
}
|
||||
if (*y + *h > dh)
|
||||
return -EINVAL;
|
||||
|
||||
/* returns 1 for async op, and 0 for sync op */
|
||||
static int do_update(struct omap_dss_device *dssdev, struct update_region *upd)
|
||||
{
|
||||
u16 x = upd->x;
|
||||
u16 y = upd->y;
|
||||
u16 w = upd->w;
|
||||
u16 h = upd->h;
|
||||
if (*w == 1)
|
||||
return -EINVAL;
|
||||
|
||||
perf_mark_setup();
|
||||
if (*w == 0 || *h == 0)
|
||||
return -EINVAL;
|
||||
|
||||
if (dssdev->manager->caps & OMAP_DSS_OVL_MGR_CAP_DISPC) {
|
||||
/*dssdev->driver->enable_te(dssdev, 1); */
|
||||
dss_setup_partial_planes(dssdev, &x, &y, &w, &h);
|
||||
dss_setup_partial_planes(dssdev, x, y, w, h);
|
||||
dispc_set_lcd_size(*w, *h);
|
||||
}
|
||||
|
||||
#ifdef MEASURE_PERF
|
||||
rfbi.perf_bytes = w * h * 2; /* XXX always 16bit */
|
||||
#endif
|
||||
|
||||
dssdev->driver->setup_update(dssdev, x, y, w, h);
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL(omap_rfbi_prepare_update);
|
||||
|
||||
int omap_rfbi_update(struct omap_dss_device *dssdev,
|
||||
u16 x, u16 y, u16 w, u16 h,
|
||||
void (*callback)(void *), void *data)
|
||||
{
|
||||
if (dssdev->manager->caps & OMAP_DSS_OVL_MGR_CAP_DISPC) {
|
||||
rfbi_transfer_area(w, h, NULL, NULL);
|
||||
return 1;
|
||||
rfbi_transfer_area(w, h, callback, data);
|
||||
} else {
|
||||
struct omap_overlay *ovl;
|
||||
void __iomem *addr;
|
||||
|
@ -994,123 +911,12 @@ static int do_update(struct omap_dss_device *dssdev, struct update_region *upd)
|
|||
|
||||
omap_rfbi_write_pixels(addr, scr_width, x, y, w, h);
|
||||
|
||||
perf_show("L4");
|
||||
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
static void process_cmd_fifo(void)
|
||||
{
|
||||
int len;
|
||||
struct update_param p;
|
||||
struct omap_dss_device *dssdev;
|
||||
unsigned long flags;
|
||||
|
||||
if (atomic_inc_return(&rfbi.cmd_pending) != 1)
|
||||
return;
|
||||
|
||||
while (true) {
|
||||
spin_lock_irqsave(&rfbi.cmd_lock, flags);
|
||||
|
||||
len = kfifo_out(&rfbi.cmd_fifo, (unsigned char *)&p,
|
||||
sizeof(struct update_param));
|
||||
if (len == 0) {
|
||||
DSSDBG("nothing more in fifo\n");
|
||||
atomic_set(&rfbi.cmd_pending, 0);
|
||||
spin_unlock_irqrestore(&rfbi.cmd_lock, flags);
|
||||
break;
|
||||
}
|
||||
|
||||
/* DSSDBG("fifo full %d\n", rfbi.cmd_fifo_full.counter);*/
|
||||
|
||||
spin_unlock_irqrestore(&rfbi.cmd_lock, flags);
|
||||
|
||||
BUG_ON(len != sizeof(struct update_param));
|
||||
BUG_ON(p.rfbi_module > 1);
|
||||
|
||||
dssdev = rfbi.dssdev[p.rfbi_module];
|
||||
|
||||
if (p.cmd == RFBI_CMD_UPDATE) {
|
||||
if (do_update(dssdev, &p.par.r))
|
||||
break; /* async op */
|
||||
} else if (p.cmd == RFBI_CMD_SYNC) {
|
||||
DSSDBG("Signaling SYNC done!\n");
|
||||
complete(p.par.sync);
|
||||
} else
|
||||
BUG();
|
||||
callback(data);
|
||||
}
|
||||
|
||||
signal_fifo_waiters();
|
||||
}
|
||||
|
||||
static void rfbi_push_cmd(struct update_param *p)
|
||||
{
|
||||
int ret;
|
||||
|
||||
while (1) {
|
||||
unsigned long flags;
|
||||
int available;
|
||||
|
||||
spin_lock_irqsave(&rfbi.cmd_lock, flags);
|
||||
available = RFBI_CMD_FIFO_LEN_BYTES -
|
||||
kfifo_len(&rfbi.cmd_fifo);
|
||||
|
||||
/* DSSDBG("%d bytes left in fifo\n", available); */
|
||||
if (available < sizeof(struct update_param)) {
|
||||
DSSDBG("Going to wait because FIFO FULL..\n");
|
||||
spin_unlock_irqrestore(&rfbi.cmd_lock, flags);
|
||||
atomic_inc(&rfbi.cmd_fifo_full);
|
||||
wait_for_completion(&rfbi.cmd_done);
|
||||
/*DSSDBG("Woke up because fifo not full anymore\n");*/
|
||||
continue;
|
||||
}
|
||||
|
||||
ret = kfifo_in(&rfbi.cmd_fifo, (unsigned char *)p,
|
||||
sizeof(struct update_param));
|
||||
/* DSSDBG("pushed %d bytes\n", ret);*/
|
||||
|
||||
spin_unlock_irqrestore(&rfbi.cmd_lock, flags);
|
||||
|
||||
BUG_ON(ret != sizeof(struct update_param));
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void rfbi_push_update(int rfbi_module, int x, int y, int w, int h)
|
||||
{
|
||||
struct update_param p;
|
||||
|
||||
p.rfbi_module = rfbi_module;
|
||||
p.cmd = RFBI_CMD_UPDATE;
|
||||
|
||||
p.par.r.x = x;
|
||||
p.par.r.y = y;
|
||||
p.par.r.w = w;
|
||||
p.par.r.h = h;
|
||||
|
||||
DSSDBG("RFBI pushed %d,%d %dx%d\n", x, y, w, h);
|
||||
|
||||
rfbi_push_cmd(&p);
|
||||
|
||||
process_cmd_fifo();
|
||||
}
|
||||
|
||||
static void rfbi_push_sync(int rfbi_module, struct completion *sync_comp)
|
||||
{
|
||||
struct update_param p;
|
||||
|
||||
p.rfbi_module = rfbi_module;
|
||||
p.cmd = RFBI_CMD_SYNC;
|
||||
p.par.sync = sync_comp;
|
||||
|
||||
rfbi_push_cmd(&p);
|
||||
|
||||
DSSDBG("RFBI sync pushed to cmd fifo\n");
|
||||
|
||||
process_cmd_fifo();
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL(omap_rfbi_update);
|
||||
|
||||
void rfbi_dump_regs(struct seq_file *s)
|
||||
{
|
||||
|
@ -1155,12 +961,8 @@ int rfbi_init(void)
|
|||
{
|
||||
u32 rev;
|
||||
u32 l;
|
||||
int r;
|
||||
|
||||
spin_lock_init(&rfbi.cmd_lock);
|
||||
r = kfifo_alloc(&rfbi.cmd_fifo, RFBI_CMD_FIFO_LEN_BYTES, GFP_KERNEL);
|
||||
if (r)
|
||||
return r;
|
||||
|
||||
init_completion(&rfbi.cmd_done);
|
||||
atomic_set(&rfbi.cmd_fifo_full, 0);
|
||||
|
@ -1196,49 +998,10 @@ void rfbi_exit(void)
|
|||
{
|
||||
DSSDBG("rfbi_exit\n");
|
||||
|
||||
kfifo_free(&rfbi.cmd_fifo);
|
||||
|
||||
iounmap(rfbi.base);
|
||||
}
|
||||
|
||||
/* struct omap_display support */
|
||||
static int rfbi_display_update(struct omap_dss_device *dssdev,
|
||||
u16 x, u16 y, u16 w, u16 h)
|
||||
{
|
||||
int rfbi_module;
|
||||
|
||||
if (w == 0 || h == 0)
|
||||
return 0;
|
||||
|
||||
rfbi_module = rfbi_find_display(dssdev);
|
||||
|
||||
rfbi_push_update(rfbi_module, x, y, w, h);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int rfbi_display_sync(struct omap_dss_device *dssdev)
|
||||
{
|
||||
struct completion sync_comp;
|
||||
int rfbi_module;
|
||||
|
||||
rfbi_module = rfbi_find_display(dssdev);
|
||||
|
||||
init_completion(&sync_comp);
|
||||
rfbi_push_sync(rfbi_module, &sync_comp);
|
||||
DSSDBG("Waiting for SYNC to happen...\n");
|
||||
wait_for_completion(&sync_comp);
|
||||
DSSDBG("Released from SYNC\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int rfbi_display_enable_te(struct omap_dss_device *dssdev, bool enable)
|
||||
{
|
||||
dssdev->driver->enable_te(dssdev, enable);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int rfbi_display_enable(struct omap_dss_device *dssdev)
|
||||
int omapdss_rfbi_display_enable(struct omap_dss_device *dssdev)
|
||||
{
|
||||
int r;
|
||||
|
||||
|
@ -1269,41 +1032,25 @@ static int rfbi_display_enable(struct omap_dss_device *dssdev)
|
|||
&dssdev->ctrl.rfbi_timings);
|
||||
|
||||
|
||||
if (dssdev->driver->enable) {
|
||||
r = dssdev->driver->enable(dssdev);
|
||||
if (r)
|
||||
goto err2;
|
||||
}
|
||||
|
||||
return 0;
|
||||
err2:
|
||||
omap_dispc_unregister_isr(framedone_callback, NULL,
|
||||
DISPC_IRQ_FRAMEDONE);
|
||||
err1:
|
||||
omap_dss_stop_device(dssdev);
|
||||
err0:
|
||||
return r;
|
||||
}
|
||||
EXPORT_SYMBOL(omapdss_rfbi_display_enable);
|
||||
|
||||
static void rfbi_display_disable(struct omap_dss_device *dssdev)
|
||||
void omapdss_rfbi_display_disable(struct omap_dss_device *dssdev)
|
||||
{
|
||||
dssdev->driver->disable(dssdev);
|
||||
omap_dispc_unregister_isr(framedone_callback, NULL,
|
||||
DISPC_IRQ_FRAMEDONE);
|
||||
omap_dss_stop_device(dssdev);
|
||||
}
|
||||
EXPORT_SYMBOL(omapdss_rfbi_display_disable);
|
||||
|
||||
int rfbi_init_display(struct omap_dss_device *dssdev)
|
||||
{
|
||||
dssdev->enable = rfbi_display_enable;
|
||||
dssdev->disable = rfbi_display_disable;
|
||||
dssdev->update = rfbi_display_update;
|
||||
dssdev->sync = rfbi_display_sync;
|
||||
dssdev->enable_te = rfbi_display_enable_te;
|
||||
|
||||
rfbi.dssdev[dssdev->phy.rfbi.channel] = dssdev;
|
||||
|
||||
dssdev->caps = OMAP_DSS_DISPLAY_CAP_MANUAL_UPDATE;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -41,7 +41,7 @@ static void sdi_basic_init(void)
|
|||
dispc_lcd_enable_signal_polarity(1);
|
||||
}
|
||||
|
||||
static int sdi_display_enable(struct omap_dss_device *dssdev)
|
||||
int omapdss_sdi_display_enable(struct omap_dss_device *dssdev)
|
||||
{
|
||||
struct omap_video_timings *t = &dssdev->panel.timings;
|
||||
struct dss_clock_info dss_cinfo;
|
||||
|
@ -57,12 +57,6 @@ static int sdi_display_enable(struct omap_dss_device *dssdev)
|
|||
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);
|
||||
|
@ -119,7 +113,7 @@ static int sdi_display_enable(struct omap_dss_device *dssdev)
|
|||
mdelay(2);
|
||||
}
|
||||
|
||||
dispc_enable_lcd_out(1);
|
||||
dssdev->manager->enable(dssdev->manager);
|
||||
|
||||
if (dssdev->driver->enable) {
|
||||
r = dssdev->driver->enable(dssdev);
|
||||
|
@ -127,13 +121,11 @@ static int sdi_display_enable(struct omap_dss_device *dssdev)
|
|||
goto err3;
|
||||
}
|
||||
|
||||
dssdev->state = OMAP_DSS_DISPLAY_ACTIVE;
|
||||
|
||||
sdi.skip_init = 0;
|
||||
|
||||
return 0;
|
||||
err3:
|
||||
dispc_enable_lcd_out(0);
|
||||
dssdev->manager->disable(dssdev->manager);
|
||||
err2:
|
||||
dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK1);
|
||||
err1:
|
||||
|
@ -141,120 +133,27 @@ err1:
|
|||
err0:
|
||||
return r;
|
||||
}
|
||||
EXPORT_SYMBOL(omapdss_sdi_display_enable);
|
||||
|
||||
static int sdi_display_resume(struct omap_dss_device *dssdev);
|
||||
|
||||
static void sdi_display_disable(struct omap_dss_device *dssdev)
|
||||
void omapdss_sdi_display_disable(struct omap_dss_device *dssdev)
|
||||
{
|
||||
if (dssdev->state == OMAP_DSS_DISPLAY_DISABLED)
|
||||
return;
|
||||
|
||||
if (dssdev->state == OMAP_DSS_DISPLAY_SUSPENDED)
|
||||
if (sdi_display_resume(dssdev))
|
||||
return;
|
||||
|
||||
if (dssdev->driver->disable)
|
||||
dssdev->driver->disable(dssdev);
|
||||
|
||||
dispc_enable_lcd_out(0);
|
||||
dssdev->manager->disable(dssdev->manager);
|
||||
|
||||
dss_sdi_disable();
|
||||
|
||||
dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK1);
|
||||
|
||||
dssdev->state = OMAP_DSS_DISPLAY_DISABLED;
|
||||
|
||||
omap_dss_stop_device(dssdev);
|
||||
}
|
||||
|
||||
static int sdi_display_suspend(struct omap_dss_device *dssdev)
|
||||
{
|
||||
if (dssdev->state != OMAP_DSS_DISPLAY_ACTIVE)
|
||||
return -EINVAL;
|
||||
|
||||
if (dssdev->driver->suspend)
|
||||
dssdev->driver->suspend(dssdev);
|
||||
|
||||
dispc_enable_lcd_out(0);
|
||||
|
||||
dss_sdi_disable();
|
||||
|
||||
dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK1);
|
||||
|
||||
dssdev->state = OMAP_DSS_DISPLAY_SUSPENDED;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int sdi_display_resume(struct omap_dss_device *dssdev)
|
||||
{
|
||||
int r;
|
||||
|
||||
if (dssdev->state != OMAP_DSS_DISPLAY_SUSPENDED)
|
||||
return -EINVAL;
|
||||
|
||||
dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK1);
|
||||
|
||||
r = dss_sdi_enable();
|
||||
if (r)
|
||||
goto err;
|
||||
mdelay(2);
|
||||
|
||||
dispc_enable_lcd_out(1);
|
||||
|
||||
if (dssdev->driver->resume)
|
||||
dssdev->driver->resume(dssdev);
|
||||
|
||||
dssdev->state = OMAP_DSS_DISPLAY_ACTIVE;
|
||||
|
||||
return 0;
|
||||
err:
|
||||
dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK1);
|
||||
return r;
|
||||
}
|
||||
|
||||
static int sdi_display_set_update_mode(struct omap_dss_device *dssdev,
|
||||
enum omap_dss_update_mode mode)
|
||||
{
|
||||
if (mode == OMAP_DSS_UPDATE_MANUAL)
|
||||
return -EINVAL;
|
||||
|
||||
if (mode == OMAP_DSS_UPDATE_DISABLED) {
|
||||
dispc_enable_lcd_out(0);
|
||||
sdi.update_enabled = 0;
|
||||
} else {
|
||||
dispc_enable_lcd_out(1);
|
||||
sdi.update_enabled = 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static enum omap_dss_update_mode sdi_display_get_update_mode(
|
||||
struct omap_dss_device *dssdev)
|
||||
{
|
||||
return sdi.update_enabled ? OMAP_DSS_UPDATE_AUTO :
|
||||
OMAP_DSS_UPDATE_DISABLED;
|
||||
}
|
||||
|
||||
static void sdi_get_timings(struct omap_dss_device *dssdev,
|
||||
struct omap_video_timings *timings)
|
||||
{
|
||||
*timings = dssdev->panel.timings;
|
||||
}
|
||||
EXPORT_SYMBOL(omapdss_sdi_display_disable);
|
||||
|
||||
int sdi_init_display(struct omap_dss_device *dssdev)
|
||||
{
|
||||
DSSDBG("SDI init\n");
|
||||
|
||||
dssdev->enable = sdi_display_enable;
|
||||
dssdev->disable = sdi_display_disable;
|
||||
dssdev->suspend = sdi_display_suspend;
|
||||
dssdev->resume = sdi_display_resume;
|
||||
dssdev->set_update_mode = sdi_display_set_update_mode;
|
||||
dssdev->get_update_mode = sdi_display_get_update_mode;
|
||||
dssdev->get_timings = sdi_get_timings;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -400,114 +400,6 @@ static const struct venc_config *venc_timings_to_config(
|
|||
BUG();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/* driver */
|
||||
static int venc_panel_probe(struct omap_dss_device *dssdev)
|
||||
{
|
||||
dssdev->panel.timings = omap_dss_pal_timings;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void venc_panel_remove(struct omap_dss_device *dssdev)
|
||||
{
|
||||
}
|
||||
|
||||
static int venc_panel_enable(struct omap_dss_device *dssdev)
|
||||
{
|
||||
int r = 0;
|
||||
|
||||
/* wait couple of vsyncs until enabling the LCD */
|
||||
msleep(50);
|
||||
|
||||
if (dssdev->platform_enable)
|
||||
r = dssdev->platform_enable(dssdev);
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
static void venc_panel_disable(struct omap_dss_device *dssdev)
|
||||
{
|
||||
if (dssdev->platform_disable)
|
||||
dssdev->platform_disable(dssdev);
|
||||
|
||||
/* wait at least 5 vsyncs after disabling the LCD */
|
||||
|
||||
msleep(100);
|
||||
}
|
||||
|
||||
static int venc_panel_suspend(struct omap_dss_device *dssdev)
|
||||
{
|
||||
venc_panel_disable(dssdev);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int venc_panel_resume(struct omap_dss_device *dssdev)
|
||||
{
|
||||
return venc_panel_enable(dssdev);
|
||||
}
|
||||
|
||||
static struct omap_dss_driver venc_driver = {
|
||||
.probe = venc_panel_probe,
|
||||
.remove = venc_panel_remove,
|
||||
|
||||
.enable = venc_panel_enable,
|
||||
.disable = venc_panel_disable,
|
||||
.suspend = venc_panel_suspend,
|
||||
.resume = venc_panel_resume,
|
||||
|
||||
.driver = {
|
||||
.name = "venc",
|
||||
.owner = THIS_MODULE,
|
||||
},
|
||||
};
|
||||
/* driver end */
|
||||
|
||||
|
||||
|
||||
int venc_init(struct platform_device *pdev)
|
||||
{
|
||||
u8 rev_id;
|
||||
|
||||
mutex_init(&venc.venc_lock);
|
||||
|
||||
venc.wss_data = 0;
|
||||
|
||||
venc.base = ioremap(VENC_BASE, SZ_1K);
|
||||
if (!venc.base) {
|
||||
DSSERR("can't ioremap VENC\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
venc.vdda_dac_reg = regulator_get(&pdev->dev, "vdda_dac");
|
||||
if (IS_ERR(venc.vdda_dac_reg)) {
|
||||
iounmap(venc.base);
|
||||
DSSERR("can't get VDDA_DAC regulator\n");
|
||||
return PTR_ERR(venc.vdda_dac_reg);
|
||||
}
|
||||
|
||||
venc_enable_clocks(1);
|
||||
|
||||
rev_id = (u8)(venc_read_reg(VENC_REV_ID) & 0xff);
|
||||
printk(KERN_INFO "OMAP VENC rev %d\n", rev_id);
|
||||
|
||||
venc_enable_clocks(0);
|
||||
|
||||
return omap_dss_register_driver(&venc_driver);
|
||||
}
|
||||
|
||||
void venc_exit(void)
|
||||
{
|
||||
omap_dss_unregister_driver(&venc_driver);
|
||||
|
||||
regulator_put(venc.vdda_dac_reg);
|
||||
|
||||
iounmap(venc.base);
|
||||
}
|
||||
|
||||
static void venc_power_on(struct omap_dss_device *dssdev)
|
||||
{
|
||||
u32 l;
|
||||
|
@ -540,7 +432,7 @@ static void venc_power_on(struct omap_dss_device *dssdev)
|
|||
if (dssdev->platform_enable)
|
||||
dssdev->platform_enable(dssdev);
|
||||
|
||||
dispc_enable_digit_out(1);
|
||||
dssdev->manager->enable(dssdev->manager);
|
||||
}
|
||||
|
||||
static void venc_power_off(struct omap_dss_device *dssdev)
|
||||
|
@ -548,7 +440,7 @@ static void venc_power_off(struct omap_dss_device *dssdev)
|
|||
venc_write_reg(VENC_OUTPUT_CONTROL, 0);
|
||||
dss_set_dac_pwrdn_bgz(0);
|
||||
|
||||
dispc_enable_digit_out(0);
|
||||
dssdev->manager->disable(dssdev->manager);
|
||||
|
||||
if (dssdev->platform_disable)
|
||||
dssdev->platform_disable(dssdev);
|
||||
|
@ -558,7 +450,23 @@ static void venc_power_off(struct omap_dss_device *dssdev)
|
|||
venc_enable_clocks(0);
|
||||
}
|
||||
|
||||
static int venc_enable_display(struct omap_dss_device *dssdev)
|
||||
|
||||
|
||||
|
||||
|
||||
/* driver */
|
||||
static int venc_panel_probe(struct omap_dss_device *dssdev)
|
||||
{
|
||||
dssdev->panel.timings = omap_dss_pal_timings;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void venc_panel_remove(struct omap_dss_device *dssdev)
|
||||
{
|
||||
}
|
||||
|
||||
static int venc_panel_enable(struct omap_dss_device *dssdev)
|
||||
{
|
||||
int r = 0;
|
||||
|
||||
|
@ -568,7 +476,13 @@ static int venc_enable_display(struct omap_dss_device *dssdev)
|
|||
|
||||
if (dssdev->state != OMAP_DSS_DISPLAY_DISABLED) {
|
||||
r = -EINVAL;
|
||||
goto err;
|
||||
goto err1;
|
||||
}
|
||||
|
||||
if (dssdev->platform_enable) {
|
||||
r = dssdev->platform_enable(dssdev);
|
||||
if (r)
|
||||
goto err2;
|
||||
}
|
||||
|
||||
venc_power_on(dssdev);
|
||||
|
@ -576,13 +490,21 @@ static int venc_enable_display(struct omap_dss_device *dssdev)
|
|||
venc.wss_data = 0;
|
||||
|
||||
dssdev->state = OMAP_DSS_DISPLAY_ACTIVE;
|
||||
err:
|
||||
|
||||
/* wait couple of vsyncs until enabling the LCD */
|
||||
msleep(50);
|
||||
|
||||
mutex_unlock(&venc.venc_lock);
|
||||
|
||||
return r;
|
||||
err2:
|
||||
venc_power_off(dssdev);
|
||||
err1:
|
||||
mutex_unlock(&venc.venc_lock);
|
||||
return r;
|
||||
}
|
||||
|
||||
static void venc_disable_display(struct omap_dss_device *dssdev)
|
||||
static void venc_panel_disable(struct omap_dss_device *dssdev)
|
||||
{
|
||||
DSSDBG("venc_disable_display\n");
|
||||
|
||||
|
@ -599,53 +521,40 @@ static void venc_disable_display(struct omap_dss_device *dssdev)
|
|||
|
||||
venc_power_off(dssdev);
|
||||
|
||||
/* wait at least 5 vsyncs after disabling the LCD */
|
||||
msleep(100);
|
||||
|
||||
if (dssdev->platform_disable)
|
||||
dssdev->platform_disable(dssdev);
|
||||
|
||||
dssdev->state = OMAP_DSS_DISPLAY_DISABLED;
|
||||
end:
|
||||
mutex_unlock(&venc.venc_lock);
|
||||
}
|
||||
|
||||
static int venc_display_suspend(struct omap_dss_device *dssdev)
|
||||
static int venc_panel_suspend(struct omap_dss_device *dssdev)
|
||||
{
|
||||
int r = 0;
|
||||
|
||||
DSSDBG("venc_display_suspend\n");
|
||||
|
||||
mutex_lock(&venc.venc_lock);
|
||||
|
||||
if (dssdev->state != OMAP_DSS_DISPLAY_ACTIVE) {
|
||||
r = -EINVAL;
|
||||
goto err;
|
||||
}
|
||||
|
||||
venc_power_off(dssdev);
|
||||
|
||||
dssdev->state = OMAP_DSS_DISPLAY_SUSPENDED;
|
||||
err:
|
||||
mutex_unlock(&venc.venc_lock);
|
||||
|
||||
return r;
|
||||
venc_panel_disable(dssdev);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int venc_display_resume(struct omap_dss_device *dssdev)
|
||||
static int venc_panel_resume(struct omap_dss_device *dssdev)
|
||||
{
|
||||
int r = 0;
|
||||
return venc_panel_enable(dssdev);
|
||||
}
|
||||
|
||||
DSSDBG("venc_display_resume\n");
|
||||
static enum omap_dss_update_mode venc_get_update_mode(
|
||||
struct omap_dss_device *dssdev)
|
||||
{
|
||||
return OMAP_DSS_UPDATE_AUTO;
|
||||
}
|
||||
|
||||
mutex_lock(&venc.venc_lock);
|
||||
|
||||
if (dssdev->state != OMAP_DSS_DISPLAY_SUSPENDED) {
|
||||
r = -EINVAL;
|
||||
goto err;
|
||||
}
|
||||
|
||||
venc_power_on(dssdev);
|
||||
|
||||
dssdev->state = OMAP_DSS_DISPLAY_ACTIVE;
|
||||
err:
|
||||
mutex_unlock(&venc.venc_lock);
|
||||
|
||||
return r;
|
||||
static int venc_set_update_mode(struct omap_dss_device *dssdev,
|
||||
enum omap_dss_update_mode mode)
|
||||
{
|
||||
if (mode != OMAP_DSS_UPDATE_AUTO)
|
||||
return -EINVAL;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void venc_get_timings(struct omap_dss_device *dssdev,
|
||||
|
@ -666,8 +575,8 @@ static void venc_set_timings(struct omap_dss_device *dssdev,
|
|||
dssdev->panel.timings = *timings;
|
||||
if (dssdev->state == OMAP_DSS_DISPLAY_ACTIVE) {
|
||||
/* turn the venc off and on to get new timings to use */
|
||||
venc_disable_display(dssdev);
|
||||
venc_enable_display(dssdev);
|
||||
venc_panel_disable(dssdev);
|
||||
venc_panel_enable(dssdev);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -716,30 +625,79 @@ static int venc_set_wss(struct omap_dss_device *dssdev, u32 wss)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static enum omap_dss_update_mode venc_display_get_update_mode(
|
||||
struct omap_dss_device *dssdev)
|
||||
static struct omap_dss_driver venc_driver = {
|
||||
.probe = venc_panel_probe,
|
||||
.remove = venc_panel_remove,
|
||||
|
||||
.enable = venc_panel_enable,
|
||||
.disable = venc_panel_disable,
|
||||
.suspend = venc_panel_suspend,
|
||||
.resume = venc_panel_resume,
|
||||
|
||||
.get_resolution = omapdss_default_get_resolution,
|
||||
.get_recommended_bpp = omapdss_default_get_recommended_bpp,
|
||||
|
||||
.set_update_mode = venc_set_update_mode,
|
||||
.get_update_mode = venc_get_update_mode,
|
||||
|
||||
.get_timings = venc_get_timings,
|
||||
.set_timings = venc_set_timings,
|
||||
.check_timings = venc_check_timings,
|
||||
|
||||
.get_wss = venc_get_wss,
|
||||
.set_wss = venc_set_wss,
|
||||
|
||||
.driver = {
|
||||
.name = "venc",
|
||||
.owner = THIS_MODULE,
|
||||
},
|
||||
};
|
||||
/* driver end */
|
||||
|
||||
|
||||
|
||||
int venc_init(struct platform_device *pdev)
|
||||
{
|
||||
if (dssdev->state == OMAP_DSS_DISPLAY_ACTIVE)
|
||||
return OMAP_DSS_UPDATE_AUTO;
|
||||
else
|
||||
return OMAP_DSS_UPDATE_DISABLED;
|
||||
u8 rev_id;
|
||||
|
||||
mutex_init(&venc.venc_lock);
|
||||
|
||||
venc.wss_data = 0;
|
||||
|
||||
venc.base = ioremap(VENC_BASE, SZ_1K);
|
||||
if (!venc.base) {
|
||||
DSSERR("can't ioremap VENC\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
venc.vdda_dac_reg = dss_get_vdda_dac();
|
||||
if (IS_ERR(venc.vdda_dac_reg)) {
|
||||
iounmap(venc.base);
|
||||
DSSERR("can't get VDDA_DAC regulator\n");
|
||||
return PTR_ERR(venc.vdda_dac_reg);
|
||||
}
|
||||
|
||||
venc_enable_clocks(1);
|
||||
|
||||
rev_id = (u8)(venc_read_reg(VENC_REV_ID) & 0xff);
|
||||
printk(KERN_INFO "OMAP VENC rev %d\n", rev_id);
|
||||
|
||||
venc_enable_clocks(0);
|
||||
|
||||
return omap_dss_register_driver(&venc_driver);
|
||||
}
|
||||
|
||||
void venc_exit(void)
|
||||
{
|
||||
omap_dss_unregister_driver(&venc_driver);
|
||||
|
||||
iounmap(venc.base);
|
||||
}
|
||||
|
||||
int venc_init_display(struct omap_dss_device *dssdev)
|
||||
{
|
||||
DSSDBG("init_display\n");
|
||||
|
||||
dssdev->enable = venc_enable_display;
|
||||
dssdev->disable = venc_disable_display;
|
||||
dssdev->suspend = venc_display_suspend;
|
||||
dssdev->resume = venc_display_resume;
|
||||
dssdev->get_timings = venc_get_timings;
|
||||
dssdev->set_timings = venc_set_timings;
|
||||
dssdev->check_timings = venc_check_timings;
|
||||
dssdev->get_wss = venc_get_wss;
|
||||
dssdev->set_wss = venc_set_wss;
|
||||
dssdev->get_update_mode = venc_display_get_update_mode;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -16,16 +16,7 @@ config FB_OMAP2_DEBUG_SUPPORT
|
|||
depends on FB_OMAP2
|
||||
help
|
||||
Support for debug output. You have to enable the actual printing
|
||||
with debug module parameter.
|
||||
|
||||
config FB_OMAP2_FORCE_AUTO_UPDATE
|
||||
bool "Force main display to automatic update mode"
|
||||
depends on FB_OMAP2
|
||||
help
|
||||
Forces main display to automatic update mode (if possible),
|
||||
and also enables tearsync (if possible). By default
|
||||
displays that support manual update are started in manual
|
||||
update mode.
|
||||
with 'debug' module parameter.
|
||||
|
||||
config FB_OMAP2_NUM_FBS
|
||||
int "Number of framebuffers"
|
||||
|
|
|
@ -167,12 +167,12 @@ static int omapfb_update_window_nolock(struct fb_info *fbi,
|
|||
if (w == 0 || h == 0)
|
||||
return 0;
|
||||
|
||||
display->get_resolution(display, &dw, &dh);
|
||||
display->driver->get_resolution(display, &dw, &dh);
|
||||
|
||||
if (x + w > dw || y + h > dh)
|
||||
return -EINVAL;
|
||||
|
||||
return display->update(display, x, y, w, h);
|
||||
return display->driver->update(display, x, y, w, h);
|
||||
}
|
||||
|
||||
/* This function is exported for SGX driver use */
|
||||
|
@ -202,7 +202,7 @@ static int omapfb_set_update_mode(struct fb_info *fbi,
|
|||
enum omap_dss_update_mode um;
|
||||
int r;
|
||||
|
||||
if (!display || !display->set_update_mode)
|
||||
if (!display || !display->driver->set_update_mode)
|
||||
return -EINVAL;
|
||||
|
||||
switch (mode) {
|
||||
|
@ -222,7 +222,7 @@ static int omapfb_set_update_mode(struct fb_info *fbi,
|
|||
return -EINVAL;
|
||||
}
|
||||
|
||||
r = display->set_update_mode(display, um);
|
||||
r = display->driver->set_update_mode(display, um);
|
||||
|
||||
return r;
|
||||
}
|
||||
|
@ -233,10 +233,15 @@ static int omapfb_get_update_mode(struct fb_info *fbi,
|
|||
struct omap_dss_device *display = fb2display(fbi);
|
||||
enum omap_dss_update_mode m;
|
||||
|
||||
if (!display || !display->get_update_mode)
|
||||
if (!display)
|
||||
return -EINVAL;
|
||||
|
||||
m = display->get_update_mode(display);
|
||||
if (!display->driver->get_update_mode) {
|
||||
*mode = OMAPFB_AUTO_UPDATE;
|
||||
return 0;
|
||||
}
|
||||
|
||||
m = display->driver->get_update_mode(display);
|
||||
|
||||
switch (m) {
|
||||
case OMAP_DSS_UPDATE_DISABLED:
|
||||
|
@ -374,7 +379,7 @@ static int omapfb_memory_read(struct fb_info *fbi,
|
|||
void *buf;
|
||||
int r;
|
||||
|
||||
if (!display || !display->memory_read)
|
||||
if (!display || !display->driver->memory_read)
|
||||
return -ENOENT;
|
||||
|
||||
if (!access_ok(VERIFY_WRITE, mr->buffer, mr->buffer_size))
|
||||
|
@ -389,7 +394,7 @@ static int omapfb_memory_read(struct fb_info *fbi,
|
|||
return -ENOMEM;
|
||||
}
|
||||
|
||||
r = display->memory_read(display, buf, mr->buffer_size,
|
||||
r = display->driver->memory_read(display, buf, mr->buffer_size,
|
||||
mr->x, mr->y, mr->w, mr->h);
|
||||
|
||||
if (r > 0) {
|
||||
|
@ -483,6 +488,7 @@ int omapfb_ioctl(struct fb_info *fbi, unsigned int cmd, unsigned long arg)
|
|||
struct omapfb_memory_read memory_read;
|
||||
struct omapfb_vram_info vram_info;
|
||||
struct omapfb_tearsync_info tearsync_info;
|
||||
struct omapfb_display_info display_info;
|
||||
} p;
|
||||
|
||||
int r = 0;
|
||||
|
@ -490,18 +496,18 @@ int omapfb_ioctl(struct fb_info *fbi, unsigned int cmd, unsigned long arg)
|
|||
switch (cmd) {
|
||||
case OMAPFB_SYNC_GFX:
|
||||
DBG("ioctl SYNC_GFX\n");
|
||||
if (!display || !display->sync) {
|
||||
if (!display || !display->driver->sync) {
|
||||
/* DSS1 never returns an error here, so we neither */
|
||||
/*r = -EINVAL;*/
|
||||
break;
|
||||
}
|
||||
|
||||
r = display->sync(display);
|
||||
r = display->driver->sync(display);
|
||||
break;
|
||||
|
||||
case OMAPFB_UPDATE_WINDOW_OLD:
|
||||
DBG("ioctl UPDATE_WINDOW_OLD\n");
|
||||
if (!display || !display->update) {
|
||||
if (!display || !display->driver->update) {
|
||||
r = -EINVAL;
|
||||
break;
|
||||
}
|
||||
|
@ -519,7 +525,7 @@ int omapfb_ioctl(struct fb_info *fbi, unsigned int cmd, unsigned long arg)
|
|||
|
||||
case OMAPFB_UPDATE_WINDOW:
|
||||
DBG("ioctl UPDATE_WINDOW\n");
|
||||
if (!display || !display->update) {
|
||||
if (!display || !display->driver->update) {
|
||||
r = -EINVAL;
|
||||
break;
|
||||
}
|
||||
|
@ -648,7 +654,7 @@ int omapfb_ioctl(struct fb_info *fbi, unsigned int cmd, unsigned long arg)
|
|||
break;
|
||||
}
|
||||
|
||||
r = display->wait_vsync(display);
|
||||
r = display->manager->wait_for_vsync(display->manager);
|
||||
break;
|
||||
|
||||
case OMAPFB_WAITFORGO:
|
||||
|
@ -669,12 +675,12 @@ int omapfb_ioctl(struct fb_info *fbi, unsigned int cmd, unsigned long arg)
|
|||
r = -EFAULT;
|
||||
break;
|
||||
}
|
||||
if (!display || !display->run_test) {
|
||||
if (!display || !display->driver->run_test) {
|
||||
r = -EINVAL;
|
||||
break;
|
||||
}
|
||||
|
||||
r = display->run_test(display, p.test_num);
|
||||
r = display->driver->run_test(display, p.test_num);
|
||||
|
||||
break;
|
||||
|
||||
|
@ -684,12 +690,12 @@ int omapfb_ioctl(struct fb_info *fbi, unsigned int cmd, unsigned long arg)
|
|||
r = -EFAULT;
|
||||
break;
|
||||
}
|
||||
if (!display || !display->run_test) {
|
||||
if (!display || !display->driver->run_test) {
|
||||
r = -EINVAL;
|
||||
break;
|
||||
}
|
||||
|
||||
r = display->run_test(display, p.test_num);
|
||||
r = display->driver->run_test(display, p.test_num);
|
||||
|
||||
break;
|
||||
|
||||
|
@ -731,16 +737,40 @@ int omapfb_ioctl(struct fb_info *fbi, unsigned int cmd, unsigned long arg)
|
|||
break;
|
||||
}
|
||||
|
||||
if (!display->enable_te) {
|
||||
if (!display->driver->enable_te) {
|
||||
r = -ENODEV;
|
||||
break;
|
||||
}
|
||||
|
||||
r = display->enable_te(display, !!p.tearsync_info.enabled);
|
||||
r = display->driver->enable_te(display,
|
||||
!!p.tearsync_info.enabled);
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case OMAPFB_GET_DISPLAY_INFO: {
|
||||
u16 xres, yres;
|
||||
|
||||
DBG("ioctl GET_DISPLAY_INFO\n");
|
||||
|
||||
if (display == NULL) {
|
||||
r = -ENODEV;
|
||||
break;
|
||||
}
|
||||
|
||||
display->driver->get_resolution(display, &xres, &yres);
|
||||
|
||||
p.display_info.xres = xres;
|
||||
p.display_info.yres = yres;
|
||||
p.display_info.width = 0;
|
||||
p.display_info.height = 0;
|
||||
|
||||
if (copy_to_user((void __user *)arg, &p.display_info,
|
||||
sizeof(p.display_info)))
|
||||
r = -EFAULT;
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
dev_err(fbdev->dev, "Unknown ioctl 0x%x\n", cmd);
|
||||
r = -EINVAL;
|
||||
|
|
|
@ -54,6 +54,8 @@ module_param_named(test, omapfb_test_pattern, bool, 0644);
|
|||
#endif
|
||||
|
||||
static int omapfb_fb_init(struct omapfb2_device *fbdev, struct fb_info *fbi);
|
||||
static int omapfb_get_recommended_bpp(struct omapfb2_device *fbdev,
|
||||
struct omap_dss_device *dssdev);
|
||||
|
||||
#ifdef DEBUG
|
||||
static void draw_pixel(struct fb_info *fbi, int x, int y, unsigned color)
|
||||
|
@ -152,9 +154,9 @@ static void fill_fb(struct fb_info *fbi)
|
|||
}
|
||||
#endif
|
||||
|
||||
static unsigned omapfb_get_vrfb_offset(struct omapfb_info *ofbi, int rot)
|
||||
static unsigned omapfb_get_vrfb_offset(const struct omapfb_info *ofbi, int rot)
|
||||
{
|
||||
struct vrfb *vrfb = &ofbi->region.vrfb;
|
||||
const struct vrfb *vrfb = &ofbi->region.vrfb;
|
||||
unsigned offset;
|
||||
|
||||
switch (rot) {
|
||||
|
@ -179,7 +181,7 @@ static unsigned omapfb_get_vrfb_offset(struct omapfb_info *ofbi, int rot)
|
|||
return offset;
|
||||
}
|
||||
|
||||
static u32 omapfb_get_region_rot_paddr(struct omapfb_info *ofbi, int rot)
|
||||
static u32 omapfb_get_region_rot_paddr(const struct omapfb_info *ofbi, int rot)
|
||||
{
|
||||
if (ofbi->rotation_type == OMAP_DSS_ROT_VRFB) {
|
||||
return ofbi->region.vrfb.paddr[rot]
|
||||
|
@ -189,7 +191,7 @@ static u32 omapfb_get_region_rot_paddr(struct omapfb_info *ofbi, int rot)
|
|||
}
|
||||
}
|
||||
|
||||
static u32 omapfb_get_region_paddr(struct omapfb_info *ofbi)
|
||||
static u32 omapfb_get_region_paddr(const struct omapfb_info *ofbi)
|
||||
{
|
||||
if (ofbi->rotation_type == OMAP_DSS_ROT_VRFB)
|
||||
return ofbi->region.vrfb.paddr[0];
|
||||
|
@ -197,7 +199,7 @@ static u32 omapfb_get_region_paddr(struct omapfb_info *ofbi)
|
|||
return ofbi->region.paddr;
|
||||
}
|
||||
|
||||
static void __iomem *omapfb_get_region_vaddr(struct omapfb_info *ofbi)
|
||||
static void __iomem *omapfb_get_region_vaddr(const struct omapfb_info *ofbi)
|
||||
{
|
||||
if (ofbi->rotation_type == OMAP_DSS_ROT_VRFB)
|
||||
return ofbi->region.vrfb.vaddr[0];
|
||||
|
@ -703,9 +705,9 @@ int check_fb_var(struct fb_info *fbi, struct fb_var_screeninfo *var)
|
|||
var->width = -1;
|
||||
var->grayscale = 0;
|
||||
|
||||
if (display && display->get_timings) {
|
||||
if (display && display->driver->get_timings) {
|
||||
struct omap_video_timings timings;
|
||||
display->get_timings(display, &timings);
|
||||
display->driver->get_timings(display, &timings);
|
||||
|
||||
/* pixclock in ps, the rest in pixclock */
|
||||
var->pixclock = timings.pixel_clock != 0 ?
|
||||
|
@ -778,8 +780,8 @@ static int omapfb_release(struct fb_info *fbi, int user)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static unsigned calc_rotation_offset_dma(struct fb_var_screeninfo *var,
|
||||
struct fb_fix_screeninfo *fix, int rotation)
|
||||
static unsigned calc_rotation_offset_dma(const struct fb_var_screeninfo *var,
|
||||
const struct fb_fix_screeninfo *fix, int rotation)
|
||||
{
|
||||
unsigned offset;
|
||||
|
||||
|
@ -789,8 +791,8 @@ static unsigned calc_rotation_offset_dma(struct fb_var_screeninfo *var,
|
|||
return offset;
|
||||
}
|
||||
|
||||
static unsigned calc_rotation_offset_vrfb(struct fb_var_screeninfo *var,
|
||||
struct fb_fix_screeninfo *fix, int rotation)
|
||||
static unsigned calc_rotation_offset_vrfb(const struct fb_var_screeninfo *var,
|
||||
const struct fb_fix_screeninfo *fix, int rotation)
|
||||
{
|
||||
unsigned offset;
|
||||
|
||||
|
@ -1221,11 +1223,11 @@ static int omapfb_blank(int blank, struct fb_info *fbi)
|
|||
if (display->state != OMAP_DSS_DISPLAY_SUSPENDED)
|
||||
goto exit;
|
||||
|
||||
if (display->resume)
|
||||
r = display->resume(display);
|
||||
if (display->driver->resume)
|
||||
r = display->driver->resume(display);
|
||||
|
||||
if (r == 0 && display->get_update_mode &&
|
||||
display->get_update_mode(display) ==
|
||||
if (r == 0 && display->driver->get_update_mode &&
|
||||
display->driver->get_update_mode(display) ==
|
||||
OMAP_DSS_UPDATE_MANUAL)
|
||||
do_update = 1;
|
||||
|
||||
|
@ -1240,8 +1242,8 @@ static int omapfb_blank(int blank, struct fb_info *fbi)
|
|||
if (display->state != OMAP_DSS_DISPLAY_ACTIVE)
|
||||
goto exit;
|
||||
|
||||
if (display->suspend)
|
||||
r = display->suspend(display);
|
||||
if (display->driver->suspend)
|
||||
r = display->driver->suspend(display);
|
||||
|
||||
break;
|
||||
|
||||
|
@ -1252,11 +1254,11 @@ static int omapfb_blank(int blank, struct fb_info *fbi)
|
|||
exit:
|
||||
omapfb_unlock(fbdev);
|
||||
|
||||
if (r == 0 && do_update && display->update) {
|
||||
if (r == 0 && do_update && display->driver->update) {
|
||||
u16 w, h;
|
||||
display->get_resolution(display, &w, &h);
|
||||
display->driver->get_resolution(display, &w, &h);
|
||||
|
||||
r = display->update(display, 0, 0, w, h);
|
||||
r = display->driver->update(display, 0, 0, w, h);
|
||||
}
|
||||
|
||||
return r;
|
||||
|
@ -1404,6 +1406,7 @@ static int omapfb_alloc_fbmem_display(struct fb_info *fbi, unsigned long size,
|
|||
unsigned long paddr)
|
||||
{
|
||||
struct omapfb_info *ofbi = FB2OFB(fbi);
|
||||
struct omapfb2_device *fbdev = ofbi->fbdev;
|
||||
struct omap_dss_device *display;
|
||||
int bytespp;
|
||||
|
||||
|
@ -1412,7 +1415,7 @@ static int omapfb_alloc_fbmem_display(struct fb_info *fbi, unsigned long size,
|
|||
if (!display)
|
||||
return 0;
|
||||
|
||||
switch (display->get_recommended_bpp(display)) {
|
||||
switch (omapfb_get_recommended_bpp(fbdev, display)) {
|
||||
case 16:
|
||||
bytespp = 2;
|
||||
break;
|
||||
|
@ -1427,7 +1430,7 @@ static int omapfb_alloc_fbmem_display(struct fb_info *fbi, unsigned long size,
|
|||
if (!size) {
|
||||
u16 w, h;
|
||||
|
||||
display->get_resolution(display, &w, &h);
|
||||
display->driver->get_resolution(display, &w, &h);
|
||||
|
||||
if (ofbi->rotation_type == OMAP_DSS_ROT_VRFB) {
|
||||
size = max(omap_vrfb_min_phys_size(w, h, bytespp),
|
||||
|
@ -1636,8 +1639,8 @@ int omapfb_realloc_fbmem(struct fb_info *fbi, unsigned long size, int type)
|
|||
if (old_size == size && old_type == type)
|
||||
return 0;
|
||||
|
||||
if (display && display->sync)
|
||||
display->sync(display);
|
||||
if (display && display->driver->sync)
|
||||
display->driver->sync(display);
|
||||
|
||||
omapfb_free_fbmem(fbi);
|
||||
|
||||
|
@ -1745,7 +1748,7 @@ static int omapfb_fb_init(struct omapfb2_device *fbdev, struct fb_info *fbi)
|
|||
u16 w, h;
|
||||
int rotation = (var->rotate + ofbi->rotation[0]) % 4;
|
||||
|
||||
display->get_resolution(display, &w, &h);
|
||||
display->driver->get_resolution(display, &w, &h);
|
||||
|
||||
if (rotation == FB_ROTATE_CW ||
|
||||
rotation == FB_ROTATE_CCW) {
|
||||
|
@ -1760,7 +1763,7 @@ static int omapfb_fb_init(struct omapfb2_device *fbdev, struct fb_info *fbi)
|
|||
var->yres_virtual = var->yres;
|
||||
|
||||
if (!var->bits_per_pixel) {
|
||||
switch (display->get_recommended_bpp(display)) {
|
||||
switch (omapfb_get_recommended_bpp(fbdev, display)) {
|
||||
case 16:
|
||||
var->bits_per_pixel = 16;
|
||||
break;
|
||||
|
@ -1828,7 +1831,7 @@ static void omapfb_free_resources(struct omapfb2_device *fbdev)
|
|||
|
||||
for (i = 0; i < fbdev->num_displays; i++) {
|
||||
if (fbdev->displays[i]->state != OMAP_DSS_DISPLAY_DISABLED)
|
||||
fbdev->displays[i]->disable(fbdev->displays[i]);
|
||||
fbdev->displays[i]->driver->disable(fbdev->displays[i]);
|
||||
|
||||
omap_dss_put_device(fbdev->displays[i]);
|
||||
}
|
||||
|
@ -2011,7 +2014,8 @@ static int omapfb_mode_to_timings(const char *mode_str,
|
|||
}
|
||||
}
|
||||
|
||||
static int omapfb_set_def_mode(struct omap_dss_device *display, char *mode_str)
|
||||
static int omapfb_set_def_mode(struct omapfb2_device *fbdev,
|
||||
struct omap_dss_device *display, char *mode_str)
|
||||
{
|
||||
int r;
|
||||
u8 bpp;
|
||||
|
@ -2021,20 +2025,37 @@ static int omapfb_set_def_mode(struct omap_dss_device *display, char *mode_str)
|
|||
if (r)
|
||||
return r;
|
||||
|
||||
display->panel.recommended_bpp = bpp;
|
||||
fbdev->bpp_overrides[fbdev->num_bpp_overrides].dssdev = display;
|
||||
fbdev->bpp_overrides[fbdev->num_bpp_overrides].bpp = bpp;
|
||||
++fbdev->num_bpp_overrides;
|
||||
|
||||
if (!display->check_timings || !display->set_timings)
|
||||
if (!display->driver->check_timings || !display->driver->set_timings)
|
||||
return -EINVAL;
|
||||
|
||||
r = display->check_timings(display, &timings);
|
||||
r = display->driver->check_timings(display, &timings);
|
||||
if (r)
|
||||
return r;
|
||||
|
||||
display->set_timings(display, &timings);
|
||||
display->driver->set_timings(display, &timings);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int omapfb_get_recommended_bpp(struct omapfb2_device *fbdev,
|
||||
struct omap_dss_device *dssdev)
|
||||
{
|
||||
int i;
|
||||
|
||||
BUG_ON(dssdev->driver->get_recommended_bpp == NULL);
|
||||
|
||||
for (i = 0; i < fbdev->num_bpp_overrides; ++i) {
|
||||
if (dssdev == fbdev->bpp_overrides[i].dssdev)
|
||||
return fbdev->bpp_overrides[i].bpp;
|
||||
}
|
||||
|
||||
return dssdev->driver->get_recommended_bpp(dssdev);
|
||||
}
|
||||
|
||||
static int omapfb_parse_def_modes(struct omapfb2_device *fbdev)
|
||||
{
|
||||
char *str, *options, *this_opt;
|
||||
|
@ -2073,7 +2094,7 @@ static int omapfb_parse_def_modes(struct omapfb2_device *fbdev)
|
|||
break;
|
||||
}
|
||||
|
||||
r = omapfb_set_def_mode(display, mode_str);
|
||||
r = omapfb_set_def_mode(fbdev, display, mode_str);
|
||||
if (r)
|
||||
break;
|
||||
}
|
||||
|
@ -2111,18 +2132,23 @@ static int omapfb_probe(struct platform_device *pdev)
|
|||
fbdev->dev = &pdev->dev;
|
||||
platform_set_drvdata(pdev, fbdev);
|
||||
|
||||
r = 0;
|
||||
fbdev->num_displays = 0;
|
||||
dssdev = NULL;
|
||||
for_each_dss_dev(dssdev) {
|
||||
omap_dss_get_device(dssdev);
|
||||
|
||||
if (!dssdev->driver) {
|
||||
dev_err(&pdev->dev, "no driver for display\n");
|
||||
r = -EINVAL;
|
||||
goto cleanup;
|
||||
r = -ENODEV;
|
||||
}
|
||||
|
||||
fbdev->displays[fbdev->num_displays++] = dssdev;
|
||||
}
|
||||
|
||||
if (r)
|
||||
goto cleanup;
|
||||
|
||||
if (fbdev->num_displays == 0) {
|
||||
dev_err(&pdev->dev, "no displays\n");
|
||||
r = -EINVAL;
|
||||
|
@ -2167,35 +2193,28 @@ static int omapfb_probe(struct platform_device *pdev)
|
|||
}
|
||||
|
||||
if (def_display) {
|
||||
#ifndef CONFIG_FB_OMAP2_FORCE_AUTO_UPDATE
|
||||
u16 w, h;
|
||||
#endif
|
||||
r = def_display->enable(def_display);
|
||||
if (r)
|
||||
struct omap_dss_driver *dssdrv = def_display->driver;
|
||||
|
||||
r = def_display->driver->enable(def_display);
|
||||
if (r) {
|
||||
dev_warn(fbdev->dev, "Failed to enable display '%s'\n",
|
||||
def_display->name);
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
/* set the update mode */
|
||||
if (def_display->caps & OMAP_DSS_DISPLAY_CAP_MANUAL_UPDATE) {
|
||||
#ifdef CONFIG_FB_OMAP2_FORCE_AUTO_UPDATE
|
||||
if (def_display->enable_te)
|
||||
def_display->enable_te(def_display, 1);
|
||||
if (def_display->set_update_mode)
|
||||
def_display->set_update_mode(def_display,
|
||||
OMAP_DSS_UPDATE_AUTO);
|
||||
#else /* MANUAL_UPDATE */
|
||||
if (def_display->enable_te)
|
||||
def_display->enable_te(def_display, 0);
|
||||
if (def_display->set_update_mode)
|
||||
def_display->set_update_mode(def_display,
|
||||
u16 w, h;
|
||||
if (dssdrv->enable_te)
|
||||
dssdrv->enable_te(def_display, 1);
|
||||
if (dssdrv->set_update_mode)
|
||||
dssdrv->set_update_mode(def_display,
|
||||
OMAP_DSS_UPDATE_MANUAL);
|
||||
|
||||
def_display->get_resolution(def_display, &w, &h);
|
||||
def_display->update(def_display, 0, 0, w, h);
|
||||
#endif
|
||||
dssdrv->get_resolution(def_display, &w, &h);
|
||||
def_display->driver->update(def_display, 0, 0, w, h);
|
||||
} else {
|
||||
if (def_display->set_update_mode)
|
||||
def_display->set_update_mode(def_display,
|
||||
if (dssdrv->set_update_mode)
|
||||
dssdrv->set_update_mode(def_display,
|
||||
OMAP_DSS_UPDATE_AUTO);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -83,6 +83,12 @@ struct omapfb2_device {
|
|||
struct omap_overlay *overlays[10];
|
||||
unsigned num_managers;
|
||||
struct omap_overlay_manager *managers[10];
|
||||
|
||||
unsigned num_bpp_overrides;
|
||||
struct {
|
||||
struct omap_dss_device *dssdev;
|
||||
u8 bpp;
|
||||
} bpp_overrides[10];
|
||||
};
|
||||
|
||||
struct omapfb_colormode {
|
||||
|
@ -105,6 +111,9 @@ void omapfb_remove_sysfs(struct omapfb2_device *fbdev);
|
|||
|
||||
int omapfb_ioctl(struct fb_info *fbi, unsigned int cmd, unsigned long arg);
|
||||
|
||||
int omapfb_update_window(struct fb_info *fbi,
|
||||
u32 x, u32 y, u32 w, u32 h);
|
||||
|
||||
int dss_mode_to_fb_mode(enum omap_color_mode dssmode,
|
||||
struct fb_var_screeninfo *var);
|
||||
|
||||
|
|
|
@ -126,6 +126,7 @@ header-y += nfs2.h
|
|||
header-y += nfs4_mount.h
|
||||
header-y += nfs_mount.h
|
||||
header-y += nl80211.h
|
||||
header-y += omapfb.h
|
||||
header-y += param.h
|
||||
header-y += pci_regs.h
|
||||
header-y += perf_event.h
|
||||
|
|
|
@ -57,6 +57,7 @@
|
|||
#define OMAPFB_WAITFORGO OMAP_IO(60)
|
||||
#define OMAPFB_GET_VRAM_INFO OMAP_IOR(61, struct omapfb_vram_info)
|
||||
#define OMAPFB_SET_TEARSYNC OMAP_IOW(62, struct omapfb_tearsync_info)
|
||||
#define OMAPFB_GET_DISPLAY_INFO OMAP_IOR(63, struct omapfb_display_info)
|
||||
|
||||
#define OMAPFB_CAPS_GENERIC_MASK 0x00000fff
|
||||
#define OMAPFB_CAPS_LCDC_MASK 0x00fff000
|
||||
|
@ -206,6 +207,14 @@ struct omapfb_tearsync_info {
|
|||
__u16 reserved2;
|
||||
};
|
||||
|
||||
struct omapfb_display_info {
|
||||
__u16 xres;
|
||||
__u16 yres;
|
||||
__u32 width; /* phys width of the display in micrometers */
|
||||
__u32 height; /* phys height of the display in micrometers */
|
||||
__u32 reserved[5];
|
||||
};
|
||||
|
||||
#ifdef __KERNEL__
|
||||
|
||||
#include <plat/board.h>
|
||||
|
|
Загрузка…
Ссылка в новой задаче