mirror of
https://github.com/torvalds/linux.git
synced 2024-11-22 20:22:09 +00:00
OMAP: DSS2: Display Subsystem Driver core
The core files of DSS2. DSS2 commits are split a bit artificially to make the individual commits smaller, and DSS2 doesn't compile properly without the rest of the core commits. This shouldn't be a problem, as no configuration uses DSS2 yet. Signed-off-by: Tomi Valkeinen <tomi.valkeinen@nokia.com>
This commit is contained in:
parent
4d1a7c122a
commit
559d670189
575
arch/arm/plat-omap/include/plat/display.h
Normal file
575
arch/arm/plat-omap/include/plat/display.h
Normal file
@ -0,0 +1,575 @@
|
||||
/*
|
||||
* linux/include/asm-arm/arch-omap/display.h
|
||||
*
|
||||
* 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/>.
|
||||
*/
|
||||
|
||||
#ifndef __ASM_ARCH_OMAP_DISPLAY_H
|
||||
#define __ASM_ARCH_OMAP_DISPLAY_H
|
||||
|
||||
#include <linux/list.h>
|
||||
#include <linux/kobject.h>
|
||||
#include <linux/device.h>
|
||||
#include <asm/atomic.h>
|
||||
|
||||
#define DISPC_IRQ_FRAMEDONE (1 << 0)
|
||||
#define DISPC_IRQ_VSYNC (1 << 1)
|
||||
#define DISPC_IRQ_EVSYNC_EVEN (1 << 2)
|
||||
#define DISPC_IRQ_EVSYNC_ODD (1 << 3)
|
||||
#define DISPC_IRQ_ACBIAS_COUNT_STAT (1 << 4)
|
||||
#define DISPC_IRQ_PROG_LINE_NUM (1 << 5)
|
||||
#define DISPC_IRQ_GFX_FIFO_UNDERFLOW (1 << 6)
|
||||
#define DISPC_IRQ_GFX_END_WIN (1 << 7)
|
||||
#define DISPC_IRQ_PAL_GAMMA_MASK (1 << 8)
|
||||
#define DISPC_IRQ_OCP_ERR (1 << 9)
|
||||
#define DISPC_IRQ_VID1_FIFO_UNDERFLOW (1 << 10)
|
||||
#define DISPC_IRQ_VID1_END_WIN (1 << 11)
|
||||
#define DISPC_IRQ_VID2_FIFO_UNDERFLOW (1 << 12)
|
||||
#define DISPC_IRQ_VID2_END_WIN (1 << 13)
|
||||
#define DISPC_IRQ_SYNC_LOST (1 << 14)
|
||||
#define DISPC_IRQ_SYNC_LOST_DIGIT (1 << 15)
|
||||
#define DISPC_IRQ_WAKEUP (1 << 16)
|
||||
|
||||
struct omap_dss_device;
|
||||
struct omap_overlay_manager;
|
||||
|
||||
enum omap_display_type {
|
||||
OMAP_DISPLAY_TYPE_NONE = 0,
|
||||
OMAP_DISPLAY_TYPE_DPI = 1 << 0,
|
||||
OMAP_DISPLAY_TYPE_DBI = 1 << 1,
|
||||
OMAP_DISPLAY_TYPE_SDI = 1 << 2,
|
||||
OMAP_DISPLAY_TYPE_DSI = 1 << 3,
|
||||
OMAP_DISPLAY_TYPE_VENC = 1 << 4,
|
||||
};
|
||||
|
||||
enum omap_plane {
|
||||
OMAP_DSS_GFX = 0,
|
||||
OMAP_DSS_VIDEO1 = 1,
|
||||
OMAP_DSS_VIDEO2 = 2
|
||||
};
|
||||
|
||||
enum omap_channel {
|
||||
OMAP_DSS_CHANNEL_LCD = 0,
|
||||
OMAP_DSS_CHANNEL_DIGIT = 1,
|
||||
};
|
||||
|
||||
enum omap_color_mode {
|
||||
OMAP_DSS_COLOR_CLUT1 = 1 << 0, /* BITMAP 1 */
|
||||
OMAP_DSS_COLOR_CLUT2 = 1 << 1, /* BITMAP 2 */
|
||||
OMAP_DSS_COLOR_CLUT4 = 1 << 2, /* BITMAP 4 */
|
||||
OMAP_DSS_COLOR_CLUT8 = 1 << 3, /* BITMAP 8 */
|
||||
OMAP_DSS_COLOR_RGB12U = 1 << 4, /* RGB12, 16-bit container */
|
||||
OMAP_DSS_COLOR_ARGB16 = 1 << 5, /* ARGB16 */
|
||||
OMAP_DSS_COLOR_RGB16 = 1 << 6, /* RGB16 */
|
||||
OMAP_DSS_COLOR_RGB24U = 1 << 7, /* RGB24, 32-bit container */
|
||||
OMAP_DSS_COLOR_RGB24P = 1 << 8, /* RGB24, 24-bit container */
|
||||
OMAP_DSS_COLOR_YUV2 = 1 << 9, /* YUV2 4:2:2 co-sited */
|
||||
OMAP_DSS_COLOR_UYVY = 1 << 10, /* UYVY 4:2:2 co-sited */
|
||||
OMAP_DSS_COLOR_ARGB32 = 1 << 11, /* ARGB32 */
|
||||
OMAP_DSS_COLOR_RGBA32 = 1 << 12, /* RGBA32 */
|
||||
OMAP_DSS_COLOR_RGBX32 = 1 << 13, /* RGBx32 */
|
||||
|
||||
OMAP_DSS_COLOR_GFX_OMAP2 =
|
||||
OMAP_DSS_COLOR_CLUT1 | OMAP_DSS_COLOR_CLUT2 |
|
||||
OMAP_DSS_COLOR_CLUT4 | OMAP_DSS_COLOR_CLUT8 |
|
||||
OMAP_DSS_COLOR_RGB12U | OMAP_DSS_COLOR_RGB16 |
|
||||
OMAP_DSS_COLOR_RGB24U | OMAP_DSS_COLOR_RGB24P,
|
||||
|
||||
OMAP_DSS_COLOR_VID_OMAP2 =
|
||||
OMAP_DSS_COLOR_RGB16 | OMAP_DSS_COLOR_RGB24U |
|
||||
OMAP_DSS_COLOR_RGB24P | OMAP_DSS_COLOR_YUV2 |
|
||||
OMAP_DSS_COLOR_UYVY,
|
||||
|
||||
OMAP_DSS_COLOR_GFX_OMAP3 =
|
||||
OMAP_DSS_COLOR_CLUT1 | OMAP_DSS_COLOR_CLUT2 |
|
||||
OMAP_DSS_COLOR_CLUT4 | OMAP_DSS_COLOR_CLUT8 |
|
||||
OMAP_DSS_COLOR_RGB12U | OMAP_DSS_COLOR_ARGB16 |
|
||||
OMAP_DSS_COLOR_RGB16 | OMAP_DSS_COLOR_RGB24U |
|
||||
OMAP_DSS_COLOR_RGB24P | OMAP_DSS_COLOR_ARGB32 |
|
||||
OMAP_DSS_COLOR_RGBA32 | OMAP_DSS_COLOR_RGBX32,
|
||||
|
||||
OMAP_DSS_COLOR_VID1_OMAP3 =
|
||||
OMAP_DSS_COLOR_RGB12U | OMAP_DSS_COLOR_RGB16 |
|
||||
OMAP_DSS_COLOR_RGB24U | OMAP_DSS_COLOR_RGB24P |
|
||||
OMAP_DSS_COLOR_YUV2 | OMAP_DSS_COLOR_UYVY,
|
||||
|
||||
OMAP_DSS_COLOR_VID2_OMAP3 =
|
||||
OMAP_DSS_COLOR_RGB12U | OMAP_DSS_COLOR_ARGB16 |
|
||||
OMAP_DSS_COLOR_RGB16 | OMAP_DSS_COLOR_RGB24U |
|
||||
OMAP_DSS_COLOR_RGB24P | OMAP_DSS_COLOR_YUV2 |
|
||||
OMAP_DSS_COLOR_UYVY | OMAP_DSS_COLOR_ARGB32 |
|
||||
OMAP_DSS_COLOR_RGBA32 | OMAP_DSS_COLOR_RGBX32,
|
||||
};
|
||||
|
||||
enum omap_lcd_display_type {
|
||||
OMAP_DSS_LCD_DISPLAY_STN,
|
||||
OMAP_DSS_LCD_DISPLAY_TFT,
|
||||
};
|
||||
|
||||
enum omap_dss_load_mode {
|
||||
OMAP_DSS_LOAD_CLUT_AND_FRAME = 0,
|
||||
OMAP_DSS_LOAD_CLUT_ONLY = 1,
|
||||
OMAP_DSS_LOAD_FRAME_ONLY = 2,
|
||||
OMAP_DSS_LOAD_CLUT_ONCE_FRAME = 3,
|
||||
};
|
||||
|
||||
enum omap_dss_trans_key_type {
|
||||
OMAP_DSS_COLOR_KEY_GFX_DST = 0,
|
||||
OMAP_DSS_COLOR_KEY_VID_SRC = 1,
|
||||
};
|
||||
|
||||
enum omap_rfbi_te_mode {
|
||||
OMAP_DSS_RFBI_TE_MODE_1 = 1,
|
||||
OMAP_DSS_RFBI_TE_MODE_2 = 2,
|
||||
};
|
||||
|
||||
enum omap_panel_config {
|
||||
OMAP_DSS_LCD_IVS = 1<<0,
|
||||
OMAP_DSS_LCD_IHS = 1<<1,
|
||||
OMAP_DSS_LCD_IPC = 1<<2,
|
||||
OMAP_DSS_LCD_IEO = 1<<3,
|
||||
OMAP_DSS_LCD_RF = 1<<4,
|
||||
OMAP_DSS_LCD_ONOFF = 1<<5,
|
||||
|
||||
OMAP_DSS_LCD_TFT = 1<<20,
|
||||
};
|
||||
|
||||
enum omap_dss_venc_type {
|
||||
OMAP_DSS_VENC_TYPE_COMPOSITE,
|
||||
OMAP_DSS_VENC_TYPE_SVIDEO,
|
||||
};
|
||||
|
||||
enum omap_display_caps {
|
||||
OMAP_DSS_DISPLAY_CAP_MANUAL_UPDATE = 1 << 0,
|
||||
OMAP_DSS_DISPLAY_CAP_TEAR_ELIM = 1 << 1,
|
||||
};
|
||||
|
||||
enum omap_dss_update_mode {
|
||||
OMAP_DSS_UPDATE_DISABLED = 0,
|
||||
OMAP_DSS_UPDATE_AUTO,
|
||||
OMAP_DSS_UPDATE_MANUAL,
|
||||
};
|
||||
|
||||
enum omap_dss_display_state {
|
||||
OMAP_DSS_DISPLAY_DISABLED = 0,
|
||||
OMAP_DSS_DISPLAY_ACTIVE,
|
||||
OMAP_DSS_DISPLAY_SUSPENDED,
|
||||
};
|
||||
|
||||
/* XXX perhaps this should be removed */
|
||||
enum omap_dss_overlay_managers {
|
||||
OMAP_DSS_OVL_MGR_LCD,
|
||||
OMAP_DSS_OVL_MGR_TV,
|
||||
};
|
||||
|
||||
enum omap_dss_rotation_type {
|
||||
OMAP_DSS_ROT_DMA = 0,
|
||||
OMAP_DSS_ROT_VRFB = 1,
|
||||
};
|
||||
|
||||
/* clockwise rotation angle */
|
||||
enum omap_dss_rotation_angle {
|
||||
OMAP_DSS_ROT_0 = 0,
|
||||
OMAP_DSS_ROT_90 = 1,
|
||||
OMAP_DSS_ROT_180 = 2,
|
||||
OMAP_DSS_ROT_270 = 3,
|
||||
};
|
||||
|
||||
enum omap_overlay_caps {
|
||||
OMAP_DSS_OVL_CAP_SCALE = 1 << 0,
|
||||
OMAP_DSS_OVL_CAP_DISPC = 1 << 1,
|
||||
};
|
||||
|
||||
enum omap_overlay_manager_caps {
|
||||
OMAP_DSS_OVL_MGR_CAP_DISPC = 1 << 0,
|
||||
};
|
||||
|
||||
/* RFBI */
|
||||
|
||||
struct rfbi_timings {
|
||||
int cs_on_time;
|
||||
int cs_off_time;
|
||||
int we_on_time;
|
||||
int we_off_time;
|
||||
int re_on_time;
|
||||
int re_off_time;
|
||||
int we_cycle_time;
|
||||
int re_cycle_time;
|
||||
int cs_pulse_width;
|
||||
int access_time;
|
||||
|
||||
int clk_div;
|
||||
|
||||
u32 tim[5]; /* set by rfbi_convert_timings() */
|
||||
|
||||
int converted;
|
||||
};
|
||||
|
||||
void omap_rfbi_write_command(const void *buf, u32 len);
|
||||
void omap_rfbi_read_data(void *buf, u32 len);
|
||||
void omap_rfbi_write_data(const void *buf, u32 len);
|
||||
void omap_rfbi_write_pixels(const void __iomem *buf, int scr_width,
|
||||
u16 x, u16 y,
|
||||
u16 w, u16 h);
|
||||
int omap_rfbi_enable_te(bool enable, unsigned line);
|
||||
int omap_rfbi_setup_te(enum omap_rfbi_te_mode mode,
|
||||
unsigned hs_pulse_time, unsigned vs_pulse_time,
|
||||
int hs_pol_inv, int vs_pol_inv, int extif_div);
|
||||
|
||||
/* DSI */
|
||||
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_nosync(int channel, u8 *data, int len);
|
||||
int dsi_vc_dcs_read(int channel, u8 dcs_cmd, u8 *buf, int buflen);
|
||||
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);
|
||||
|
||||
/* Board specific data */
|
||||
struct omap_dss_board_info {
|
||||
int (*get_last_off_on_transaction_id)(struct device *dev);
|
||||
int num_devices;
|
||||
struct omap_dss_device **devices;
|
||||
struct omap_dss_device *default_device;
|
||||
};
|
||||
|
||||
struct omap_video_timings {
|
||||
/* Unit: pixels */
|
||||
u16 x_res;
|
||||
/* Unit: pixels */
|
||||
u16 y_res;
|
||||
/* Unit: KHz */
|
||||
u32 pixel_clock;
|
||||
/* Unit: pixel clocks */
|
||||
u16 hsw; /* Horizontal synchronization pulse width */
|
||||
/* Unit: pixel clocks */
|
||||
u16 hfp; /* Horizontal front porch */
|
||||
/* Unit: pixel clocks */
|
||||
u16 hbp; /* Horizontal back porch */
|
||||
/* Unit: line clocks */
|
||||
u16 vsw; /* Vertical synchronization pulse width */
|
||||
/* Unit: line clocks */
|
||||
u16 vfp; /* Vertical front porch */
|
||||
/* Unit: line clocks */
|
||||
u16 vbp; /* Vertical back porch */
|
||||
};
|
||||
|
||||
#ifdef CONFIG_OMAP2_DSS_VENC
|
||||
/* Hardcoded timings for tv modes. Venc only uses these to
|
||||
* identify the mode, and does not actually use the configs
|
||||
* itself. However, the configs should be something that
|
||||
* a normal monitor can also show */
|
||||
const extern struct omap_video_timings omap_dss_pal_timings;
|
||||
const extern struct omap_video_timings omap_dss_ntsc_timings;
|
||||
#endif
|
||||
|
||||
struct omap_overlay_info {
|
||||
bool enabled;
|
||||
|
||||
u32 paddr;
|
||||
void __iomem *vaddr;
|
||||
u16 screen_width;
|
||||
u16 width;
|
||||
u16 height;
|
||||
enum omap_color_mode color_mode;
|
||||
u8 rotation;
|
||||
enum omap_dss_rotation_type rotation_type;
|
||||
bool mirror;
|
||||
|
||||
u16 pos_x;
|
||||
u16 pos_y;
|
||||
u16 out_width; /* if 0, out_width == width */
|
||||
u16 out_height; /* if 0, out_height == height */
|
||||
u8 global_alpha;
|
||||
};
|
||||
|
||||
struct omap_overlay {
|
||||
struct kobject kobj;
|
||||
struct list_head list;
|
||||
|
||||
/* static fields */
|
||||
const char *name;
|
||||
int id;
|
||||
enum omap_color_mode supported_modes;
|
||||
enum omap_overlay_caps caps;
|
||||
|
||||
/* dynamic fields */
|
||||
struct omap_overlay_manager *manager;
|
||||
struct omap_overlay_info info;
|
||||
|
||||
/* if true, info has been changed, but not applied() yet */
|
||||
bool info_dirty;
|
||||
|
||||
int (*set_manager)(struct omap_overlay *ovl,
|
||||
struct omap_overlay_manager *mgr);
|
||||
int (*unset_manager)(struct omap_overlay *ovl);
|
||||
|
||||
int (*set_overlay_info)(struct omap_overlay *ovl,
|
||||
struct omap_overlay_info *info);
|
||||
void (*get_overlay_info)(struct omap_overlay *ovl,
|
||||
struct omap_overlay_info *info);
|
||||
|
||||
int (*wait_for_go)(struct omap_overlay *ovl);
|
||||
};
|
||||
|
||||
struct omap_overlay_manager_info {
|
||||
u32 default_color;
|
||||
|
||||
enum omap_dss_trans_key_type trans_key_type;
|
||||
u32 trans_key;
|
||||
bool trans_enabled;
|
||||
|
||||
bool alpha_enabled;
|
||||
};
|
||||
|
||||
struct omap_overlay_manager {
|
||||
struct kobject kobj;
|
||||
struct list_head list;
|
||||
|
||||
/* static fields */
|
||||
const char *name;
|
||||
int id;
|
||||
enum omap_overlay_manager_caps caps;
|
||||
int num_overlays;
|
||||
struct omap_overlay **overlays;
|
||||
enum omap_display_type supported_displays;
|
||||
|
||||
/* dynamic fields */
|
||||
struct omap_dss_device *device;
|
||||
struct omap_overlay_manager_info info;
|
||||
|
||||
bool device_changed;
|
||||
/* if true, info has been changed but not applied() yet */
|
||||
bool info_dirty;
|
||||
|
||||
int (*set_device)(struct omap_overlay_manager *mgr,
|
||||
struct omap_dss_device *dssdev);
|
||||
int (*unset_device)(struct omap_overlay_manager *mgr);
|
||||
|
||||
int (*set_manager_info)(struct omap_overlay_manager *mgr,
|
||||
struct omap_overlay_manager_info *info);
|
||||
void (*get_manager_info)(struct omap_overlay_manager *mgr,
|
||||
struct omap_overlay_manager_info *info);
|
||||
|
||||
int (*apply)(struct omap_overlay_manager *mgr);
|
||||
int (*wait_for_go)(struct omap_overlay_manager *mgr);
|
||||
};
|
||||
|
||||
struct omap_dss_device {
|
||||
struct device dev;
|
||||
|
||||
enum omap_display_type type;
|
||||
|
||||
union {
|
||||
struct {
|
||||
u8 data_lines;
|
||||
} dpi;
|
||||
|
||||
struct {
|
||||
u8 channel;
|
||||
u8 data_lines;
|
||||
} rfbi;
|
||||
|
||||
struct {
|
||||
u8 datapairs;
|
||||
} sdi;
|
||||
|
||||
struct {
|
||||
u8 clk_lane;
|
||||
u8 clk_pol;
|
||||
u8 data1_lane;
|
||||
u8 data1_pol;
|
||||
u8 data2_lane;
|
||||
u8 data2_pol;
|
||||
|
||||
struct {
|
||||
u16 regn;
|
||||
u16 regm;
|
||||
u16 regm3;
|
||||
u16 regm4;
|
||||
|
||||
u16 lp_clk_div;
|
||||
|
||||
u16 lck_div;
|
||||
u16 pck_div;
|
||||
} div;
|
||||
|
||||
bool ext_te;
|
||||
u8 ext_te_gpio;
|
||||
} dsi;
|
||||
|
||||
struct {
|
||||
enum omap_dss_venc_type type;
|
||||
bool invert_polarity;
|
||||
} venc;
|
||||
} phy;
|
||||
|
||||
struct {
|
||||
struct omap_video_timings timings;
|
||||
|
||||
int acbi; /* ac-bias pin transitions per interrupt */
|
||||
/* Unit: line clocks */
|
||||
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;
|
||||
|
||||
int max_backlight_level;
|
||||
|
||||
const char *name;
|
||||
|
||||
/* used to match device to driver */
|
||||
const char *driver_name;
|
||||
|
||||
void *data;
|
||||
|
||||
struct omap_dss_driver *driver;
|
||||
|
||||
/* helper variable for driver suspend/resume */
|
||||
bool activate_after_resume;
|
||||
|
||||
enum omap_display_caps caps;
|
||||
|
||||
struct omap_overlay_manager *manager;
|
||||
|
||||
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);
|
||||
int (*set_backlight)(struct omap_dss_device *dssdev, int level);
|
||||
int (*get_backlight)(struct omap_dss_device *dssdev);
|
||||
};
|
||||
|
||||
struct omap_dss_driver {
|
||||
struct device_driver driver;
|
||||
|
||||
int (*probe)(struct omap_dss_device *);
|
||||
void (*remove)(struct omap_dss_device *);
|
||||
|
||||
int (*enable)(struct omap_dss_device *display);
|
||||
void (*disable)(struct omap_dss_device *display);
|
||||
int (*suspend)(struct omap_dss_device *display);
|
||||
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 (*enable_te)(struct omap_dss_device *dssdev, bool enable);
|
||||
int (*wait_for_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 (*memory_read)(struct omap_dss_device *dssdev,
|
||||
void *buf, size_t size,
|
||||
u16 x, u16 y, u16 w, u16 h);
|
||||
};
|
||||
|
||||
int omap_dss_register_driver(struct omap_dss_driver *);
|
||||
void omap_dss_unregister_driver(struct omap_dss_driver *);
|
||||
|
||||
int omap_dss_register_device(struct omap_dss_device *);
|
||||
void omap_dss_unregister_device(struct omap_dss_device *);
|
||||
|
||||
void omap_dss_get_device(struct omap_dss_device *dssdev);
|
||||
void omap_dss_put_device(struct omap_dss_device *dssdev);
|
||||
#define for_each_dss_dev(d) while ((d = omap_dss_get_next_device(d)) != NULL)
|
||||
struct omap_dss_device *omap_dss_get_next_device(struct omap_dss_device *from);
|
||||
struct omap_dss_device *omap_dss_find_device(void *data,
|
||||
int (*match)(struct omap_dss_device *dssdev, void *data));
|
||||
|
||||
int omap_dss_start_device(struct omap_dss_device *dssdev);
|
||||
void omap_dss_stop_device(struct omap_dss_device *dssdev);
|
||||
|
||||
int omap_dss_get_num_overlay_managers(void);
|
||||
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);
|
||||
|
||||
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);
|
||||
|
||||
int omap_dispc_wait_for_irq_timeout(u32 irqmask, unsigned long timeout);
|
||||
int omap_dispc_wait_for_irq_interruptible_timeout(u32 irqmask,
|
||||
unsigned long timeout);
|
||||
|
||||
#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)
|
||||
|
||||
#endif
|
@ -3,3 +3,5 @@ config OMAP2_VRAM
|
||||
|
||||
config OMAP2_VRFB
|
||||
bool
|
||||
|
||||
source "drivers/video/omap2/dss/Kconfig"
|
||||
|
@ -1,2 +1,4 @@
|
||||
obj-$(CONFIG_OMAP2_VRAM) += vram.o
|
||||
obj-$(CONFIG_OMAP2_VRFB) += vrfb.o
|
||||
|
||||
obj-y += dss/
|
||||
|
89
drivers/video/omap2/dss/Kconfig
Normal file
89
drivers/video/omap2/dss/Kconfig
Normal file
@ -0,0 +1,89 @@
|
||||
menuconfig OMAP2_DSS
|
||||
tristate "OMAP2/3 Display Subsystem support (EXPERIMENTAL)"
|
||||
depends on ARCH_OMAP2 || ARCH_OMAP3
|
||||
help
|
||||
OMAP2/3 Display Subsystem support.
|
||||
|
||||
if OMAP2_DSS
|
||||
|
||||
config OMAP2_VRAM_SIZE
|
||||
int "VRAM size (MB)"
|
||||
range 0 32
|
||||
default 0
|
||||
help
|
||||
The amount of SDRAM to reserve at boot time for video RAM use.
|
||||
This VRAM will be used by omapfb and other drivers that need
|
||||
large continuous RAM area for video use.
|
||||
|
||||
You can also set this with "vram=<bytes>" kernel argument, or
|
||||
in the board file.
|
||||
|
||||
config OMAP2_DSS_DEBUG_SUPPORT
|
||||
bool "Debug support"
|
||||
default y
|
||||
help
|
||||
This enables debug messages. You need to enable printing
|
||||
with 'debug' module parameter.
|
||||
|
||||
config OMAP2_DSS_RFBI
|
||||
bool "RFBI support"
|
||||
default n
|
||||
help
|
||||
MIPI DBI, or RFBI (Remote Framebuffer Interface), support.
|
||||
|
||||
config OMAP2_DSS_VENC
|
||||
bool "VENC support"
|
||||
default y
|
||||
help
|
||||
OMAP Video Encoder support.
|
||||
|
||||
config OMAP2_DSS_SDI
|
||||
bool "SDI support"
|
||||
depends on ARCH_OMAP3
|
||||
default n
|
||||
help
|
||||
SDI (Serial Display Interface) support.
|
||||
|
||||
config OMAP2_DSS_DSI
|
||||
bool "DSI support"
|
||||
depends on ARCH_OMAP3
|
||||
default n
|
||||
help
|
||||
MIPI DSI support.
|
||||
|
||||
config OMAP2_DSS_USE_DSI_PLL
|
||||
bool "Use DSI PLL for PCLK (EXPERIMENTAL)"
|
||||
default n
|
||||
depends on OMAP2_DSS_DSI
|
||||
help
|
||||
Use DSI PLL to generate pixel clock. Currently only for DPI output.
|
||||
DSI PLL can be used to generate higher and more precise pixel clocks.
|
||||
|
||||
config OMAP2_DSS_FAKE_VSYNC
|
||||
bool "Fake VSYNC irq from manual update displays"
|
||||
default n
|
||||
help
|
||||
If this is selected, DSI will generate a fake DISPC VSYNC interrupt
|
||||
when DSI has sent a frame. This is only needed with DSI or RFBI
|
||||
displays using manual mode, and you want VSYNC to, for example,
|
||||
time animation.
|
||||
|
||||
config OMAP2_DSS_MIN_FCK_PER_PCK
|
||||
int "Minimum FCK/PCK ratio (for scaling)"
|
||||
range 0 32
|
||||
default 0
|
||||
help
|
||||
This can be used to adjust the minimum FCK/PCK ratio.
|
||||
|
||||
With this you can make sure that DISPC FCK is at least
|
||||
n x PCK. Video plane scaling requires higher FCK than
|
||||
normally.
|
||||
|
||||
If this is set to 0, there's no extra constraint on the
|
||||
DISPC FCK. However, the FCK will at minimum be
|
||||
2xPCK (if active matrix) or 3xPCK (if passive matrix).
|
||||
|
||||
Max FCK is 173MHz, so this doesn't work if your PCK
|
||||
is very high.
|
||||
|
||||
endif
|
6
drivers/video/omap2/dss/Makefile
Normal file
6
drivers/video/omap2/dss/Makefile
Normal file
@ -0,0 +1,6 @@
|
||||
obj-$(CONFIG_OMAP2_DSS) += omapdss.o
|
||||
omapdss-y := core.o dss.o dispc.o dpi.o display.o manager.o overlay.o
|
||||
omapdss-$(CONFIG_OMAP2_DSS_RFBI) += rfbi.o
|
||||
omapdss-$(CONFIG_OMAP2_DSS_VENC) += venc.o
|
||||
omapdss-$(CONFIG_OMAP2_DSS_SDI) += sdi.o
|
||||
omapdss-$(CONFIG_OMAP2_DSS_DSI) += dsi.o
|
919
drivers/video/omap2/dss/core.c
Normal file
919
drivers/video/omap2/dss/core.c
Normal file
@ -0,0 +1,919 @@
|
||||
/*
|
||||
* linux/drivers/video/omap2/dss/core.c
|
||||
*
|
||||
* Copyright (C) 2009 Nokia Corporation
|
||||
* Author: Tomi Valkeinen <tomi.valkeinen@nokia.com>
|
||||
*
|
||||
* Some code and ideas taken from drivers/video/omap/ driver
|
||||
* by Imre Deak.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 as published by
|
||||
* the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
* more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with
|
||||
* this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#define DSS_SUBSYS_NAME "CORE"
|
||||
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/clk.h>
|
||||
#include <linux/err.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/seq_file.h>
|
||||
#include <linux/debugfs.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/device.h>
|
||||
|
||||
#include <plat/display.h>
|
||||
#include <plat/clock.h>
|
||||
|
||||
#include "dss.h"
|
||||
|
||||
static struct {
|
||||
struct platform_device *pdev;
|
||||
int ctx_id;
|
||||
|
||||
struct clk *dss_ick;
|
||||
struct clk *dss1_fck;
|
||||
struct clk *dss2_fck;
|
||||
struct clk *dss_54m_fck;
|
||||
struct clk *dss_96m_fck;
|
||||
unsigned num_clks_enabled;
|
||||
} core;
|
||||
|
||||
static void dss_clk_enable_all_no_ctx(void);
|
||||
static void dss_clk_disable_all_no_ctx(void);
|
||||
static void dss_clk_enable_no_ctx(enum dss_clock clks);
|
||||
static void dss_clk_disable_no_ctx(enum dss_clock clks);
|
||||
|
||||
static char *def_disp_name;
|
||||
module_param_named(def_disp, def_disp_name, charp, 0);
|
||||
MODULE_PARM_DESC(def_disp_name, "default display name");
|
||||
|
||||
#ifdef DEBUG
|
||||
unsigned int dss_debug;
|
||||
module_param_named(debug, dss_debug, bool, 0644);
|
||||
#endif
|
||||
|
||||
/* CONTEXT */
|
||||
static int dss_get_ctx_id(void)
|
||||
{
|
||||
struct omap_dss_board_info *pdata = core.pdev->dev.platform_data;
|
||||
int r;
|
||||
|
||||
if (!pdata->get_last_off_on_transaction_id)
|
||||
return 0;
|
||||
r = pdata->get_last_off_on_transaction_id(&core.pdev->dev);
|
||||
if (r < 0) {
|
||||
dev_err(&core.pdev->dev, "getting transaction ID failed, "
|
||||
"will force context restore\n");
|
||||
r = -1;
|
||||
}
|
||||
return r;
|
||||
}
|
||||
|
||||
int dss_need_ctx_restore(void)
|
||||
{
|
||||
int id = dss_get_ctx_id();
|
||||
|
||||
if (id < 0 || id != core.ctx_id) {
|
||||
DSSDBG("ctx id %d -> id %d\n",
|
||||
core.ctx_id, id);
|
||||
core.ctx_id = id;
|
||||
return 1;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
static void save_all_ctx(void)
|
||||
{
|
||||
DSSDBG("save context\n");
|
||||
|
||||
dss_clk_enable_no_ctx(DSS_CLK_ICK | DSS_CLK_FCK1);
|
||||
|
||||
dss_save_context();
|
||||
dispc_save_context();
|
||||
#ifdef CONFIG_OMAP2_DSS_DSI
|
||||
dsi_save_context();
|
||||
#endif
|
||||
|
||||
dss_clk_disable_no_ctx(DSS_CLK_ICK | DSS_CLK_FCK1);
|
||||
}
|
||||
|
||||
static void restore_all_ctx(void)
|
||||
{
|
||||
DSSDBG("restore context\n");
|
||||
|
||||
dss_clk_enable_all_no_ctx();
|
||||
|
||||
dss_restore_context();
|
||||
dispc_restore_context();
|
||||
#ifdef CONFIG_OMAP2_DSS_DSI
|
||||
dsi_restore_context();
|
||||
#endif
|
||||
|
||||
dss_clk_disable_all_no_ctx();
|
||||
}
|
||||
|
||||
/* CLOCKS */
|
||||
static void core_dump_clocks(struct seq_file *s)
|
||||
{
|
||||
int i;
|
||||
struct clk *clocks[5] = {
|
||||
core.dss_ick,
|
||||
core.dss1_fck,
|
||||
core.dss2_fck,
|
||||
core.dss_54m_fck,
|
||||
core.dss_96m_fck
|
||||
};
|
||||
|
||||
seq_printf(s, "- CORE -\n");
|
||||
|
||||
seq_printf(s, "internal clk count\t\t%u\n", core.num_clks_enabled);
|
||||
|
||||
for (i = 0; i < 5; i++) {
|
||||
if (!clocks[i])
|
||||
continue;
|
||||
seq_printf(s, "%-15s\t%lu\t%d\n",
|
||||
clocks[i]->name,
|
||||
clk_get_rate(clocks[i]),
|
||||
clocks[i]->usecount);
|
||||
}
|
||||
}
|
||||
|
||||
static int dss_get_clock(struct clk **clock, const char *clk_name)
|
||||
{
|
||||
struct clk *clk;
|
||||
|
||||
clk = clk_get(&core.pdev->dev, clk_name);
|
||||
|
||||
if (IS_ERR(clk)) {
|
||||
DSSERR("can't get clock %s", clk_name);
|
||||
return PTR_ERR(clk);
|
||||
}
|
||||
|
||||
*clock = clk;
|
||||
|
||||
DSSDBG("clk %s, rate %ld\n", clk_name, clk_get_rate(clk));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int dss_get_clocks(void)
|
||||
{
|
||||
int r;
|
||||
|
||||
core.dss_ick = NULL;
|
||||
core.dss1_fck = NULL;
|
||||
core.dss2_fck = NULL;
|
||||
core.dss_54m_fck = NULL;
|
||||
core.dss_96m_fck = NULL;
|
||||
|
||||
r = dss_get_clock(&core.dss_ick, "ick");
|
||||
if (r)
|
||||
goto err;
|
||||
|
||||
r = dss_get_clock(&core.dss1_fck, "dss1_fck");
|
||||
if (r)
|
||||
goto err;
|
||||
|
||||
r = dss_get_clock(&core.dss2_fck, "dss2_fck");
|
||||
if (r)
|
||||
goto err;
|
||||
|
||||
r = dss_get_clock(&core.dss_54m_fck, "tv_fck");
|
||||
if (r)
|
||||
goto err;
|
||||
|
||||
r = dss_get_clock(&core.dss_96m_fck, "video_fck");
|
||||
if (r)
|
||||
goto err;
|
||||
|
||||
return 0;
|
||||
|
||||
err:
|
||||
if (core.dss_ick)
|
||||
clk_put(core.dss_ick);
|
||||
if (core.dss1_fck)
|
||||
clk_put(core.dss1_fck);
|
||||
if (core.dss2_fck)
|
||||
clk_put(core.dss2_fck);
|
||||
if (core.dss_54m_fck)
|
||||
clk_put(core.dss_54m_fck);
|
||||
if (core.dss_96m_fck)
|
||||
clk_put(core.dss_96m_fck);
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
static void dss_put_clocks(void)
|
||||
{
|
||||
if (core.dss_96m_fck)
|
||||
clk_put(core.dss_96m_fck);
|
||||
clk_put(core.dss_54m_fck);
|
||||
clk_put(core.dss1_fck);
|
||||
clk_put(core.dss2_fck);
|
||||
clk_put(core.dss_ick);
|
||||
}
|
||||
|
||||
unsigned long dss_clk_get_rate(enum dss_clock clk)
|
||||
{
|
||||
switch (clk) {
|
||||
case DSS_CLK_ICK:
|
||||
return clk_get_rate(core.dss_ick);
|
||||
case DSS_CLK_FCK1:
|
||||
return clk_get_rate(core.dss1_fck);
|
||||
case DSS_CLK_FCK2:
|
||||
return clk_get_rate(core.dss2_fck);
|
||||
case DSS_CLK_54M:
|
||||
return clk_get_rate(core.dss_54m_fck);
|
||||
case DSS_CLK_96M:
|
||||
return clk_get_rate(core.dss_96m_fck);
|
||||
}
|
||||
|
||||
BUG();
|
||||
return 0;
|
||||
}
|
||||
|
||||
static unsigned count_clk_bits(enum dss_clock clks)
|
||||
{
|
||||
unsigned num_clks = 0;
|
||||
|
||||
if (clks & DSS_CLK_ICK)
|
||||
++num_clks;
|
||||
if (clks & DSS_CLK_FCK1)
|
||||
++num_clks;
|
||||
if (clks & DSS_CLK_FCK2)
|
||||
++num_clks;
|
||||
if (clks & DSS_CLK_54M)
|
||||
++num_clks;
|
||||
if (clks & DSS_CLK_96M)
|
||||
++num_clks;
|
||||
|
||||
return num_clks;
|
||||
}
|
||||
|
||||
static void dss_clk_enable_no_ctx(enum dss_clock clks)
|
||||
{
|
||||
unsigned num_clks = count_clk_bits(clks);
|
||||
|
||||
if (clks & DSS_CLK_ICK)
|
||||
clk_enable(core.dss_ick);
|
||||
if (clks & DSS_CLK_FCK1)
|
||||
clk_enable(core.dss1_fck);
|
||||
if (clks & DSS_CLK_FCK2)
|
||||
clk_enable(core.dss2_fck);
|
||||
if (clks & DSS_CLK_54M)
|
||||
clk_enable(core.dss_54m_fck);
|
||||
if (clks & DSS_CLK_96M)
|
||||
clk_enable(core.dss_96m_fck);
|
||||
|
||||
core.num_clks_enabled += num_clks;
|
||||
}
|
||||
|
||||
void dss_clk_enable(enum dss_clock clks)
|
||||
{
|
||||
dss_clk_enable_no_ctx(clks);
|
||||
|
||||
if (cpu_is_omap34xx() && dss_need_ctx_restore())
|
||||
restore_all_ctx();
|
||||
}
|
||||
|
||||
static void dss_clk_disable_no_ctx(enum dss_clock clks)
|
||||
{
|
||||
unsigned num_clks = count_clk_bits(clks);
|
||||
|
||||
if (clks & DSS_CLK_ICK)
|
||||
clk_disable(core.dss_ick);
|
||||
if (clks & DSS_CLK_FCK1)
|
||||
clk_disable(core.dss1_fck);
|
||||
if (clks & DSS_CLK_FCK2)
|
||||
clk_disable(core.dss2_fck);
|
||||
if (clks & DSS_CLK_54M)
|
||||
clk_disable(core.dss_54m_fck);
|
||||
if (clks & DSS_CLK_96M)
|
||||
clk_disable(core.dss_96m_fck);
|
||||
|
||||
core.num_clks_enabled -= num_clks;
|
||||
}
|
||||
|
||||
void dss_clk_disable(enum dss_clock clks)
|
||||
{
|
||||
if (cpu_is_omap34xx()) {
|
||||
unsigned num_clks = count_clk_bits(clks);
|
||||
|
||||
BUG_ON(core.num_clks_enabled < num_clks);
|
||||
|
||||
if (core.num_clks_enabled == num_clks)
|
||||
save_all_ctx();
|
||||
}
|
||||
|
||||
dss_clk_disable_no_ctx(clks);
|
||||
}
|
||||
|
||||
static void dss_clk_enable_all_no_ctx(void)
|
||||
{
|
||||
enum dss_clock clks;
|
||||
|
||||
clks = DSS_CLK_ICK | DSS_CLK_FCK1 | DSS_CLK_FCK2 | DSS_CLK_54M;
|
||||
if (cpu_is_omap34xx())
|
||||
clks |= DSS_CLK_96M;
|
||||
dss_clk_enable_no_ctx(clks);
|
||||
}
|
||||
|
||||
static void dss_clk_disable_all_no_ctx(void)
|
||||
{
|
||||
enum dss_clock clks;
|
||||
|
||||
clks = DSS_CLK_ICK | DSS_CLK_FCK1 | DSS_CLK_FCK2 | DSS_CLK_54M;
|
||||
if (cpu_is_omap34xx())
|
||||
clks |= DSS_CLK_96M;
|
||||
dss_clk_disable_no_ctx(clks);
|
||||
}
|
||||
|
||||
static void dss_clk_disable_all(void)
|
||||
{
|
||||
enum dss_clock clks;
|
||||
|
||||
clks = DSS_CLK_ICK | DSS_CLK_FCK1 | DSS_CLK_FCK2 | DSS_CLK_54M;
|
||||
if (cpu_is_omap34xx())
|
||||
clks |= DSS_CLK_96M;
|
||||
dss_clk_disable(clks);
|
||||
}
|
||||
|
||||
/* DEBUGFS */
|
||||
#if defined(CONFIG_DEBUG_FS) && defined(CONFIG_OMAP2_DSS_DEBUG_SUPPORT)
|
||||
static void dss_debug_dump_clocks(struct seq_file *s)
|
||||
{
|
||||
core_dump_clocks(s);
|
||||
dss_dump_clocks(s);
|
||||
dispc_dump_clocks(s);
|
||||
#ifdef CONFIG_OMAP2_DSS_DSI
|
||||
dsi_dump_clocks(s);
|
||||
#endif
|
||||
}
|
||||
|
||||
static int dss_debug_show(struct seq_file *s, void *unused)
|
||||
{
|
||||
void (*func)(struct seq_file *) = s->private;
|
||||
func(s);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int dss_debug_open(struct inode *inode, struct file *file)
|
||||
{
|
||||
return single_open(file, dss_debug_show, inode->i_private);
|
||||
}
|
||||
|
||||
static const struct file_operations dss_debug_fops = {
|
||||
.open = dss_debug_open,
|
||||
.read = seq_read,
|
||||
.llseek = seq_lseek,
|
||||
.release = single_release,
|
||||
};
|
||||
|
||||
static struct dentry *dss_debugfs_dir;
|
||||
|
||||
static int dss_initialize_debugfs(void)
|
||||
{
|
||||
dss_debugfs_dir = debugfs_create_dir("omapdss", NULL);
|
||||
if (IS_ERR(dss_debugfs_dir)) {
|
||||
int err = PTR_ERR(dss_debugfs_dir);
|
||||
dss_debugfs_dir = NULL;
|
||||
return err;
|
||||
}
|
||||
|
||||
debugfs_create_file("clk", S_IRUGO, dss_debugfs_dir,
|
||||
&dss_debug_dump_clocks, &dss_debug_fops);
|
||||
|
||||
debugfs_create_file("dss", S_IRUGO, dss_debugfs_dir,
|
||||
&dss_dump_regs, &dss_debug_fops);
|
||||
debugfs_create_file("dispc", S_IRUGO, dss_debugfs_dir,
|
||||
&dispc_dump_regs, &dss_debug_fops);
|
||||
#ifdef CONFIG_OMAP2_DSS_RFBI
|
||||
debugfs_create_file("rfbi", S_IRUGO, dss_debugfs_dir,
|
||||
&rfbi_dump_regs, &dss_debug_fops);
|
||||
#endif
|
||||
#ifdef CONFIG_OMAP2_DSS_DSI
|
||||
debugfs_create_file("dsi", S_IRUGO, dss_debugfs_dir,
|
||||
&dsi_dump_regs, &dss_debug_fops);
|
||||
#endif
|
||||
#ifdef CONFIG_OMAP2_DSS_VENC
|
||||
debugfs_create_file("venc", S_IRUGO, dss_debugfs_dir,
|
||||
&venc_dump_regs, &dss_debug_fops);
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void dss_uninitialize_debugfs(void)
|
||||
{
|
||||
if (dss_debugfs_dir)
|
||||
debugfs_remove_recursive(dss_debugfs_dir);
|
||||
}
|
||||
#endif /* CONFIG_DEBUG_FS && CONFIG_OMAP2_DSS_DEBUG_SUPPORT */
|
||||
|
||||
/* PLATFORM DEVICE */
|
||||
static int omap_dss_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct omap_dss_board_info *pdata = pdev->dev.platform_data;
|
||||
int skip_init = 0;
|
||||
int r;
|
||||
int i;
|
||||
|
||||
core.pdev = pdev;
|
||||
|
||||
dss_init_overlay_managers(pdev);
|
||||
dss_init_overlays(pdev);
|
||||
|
||||
r = dss_get_clocks();
|
||||
if (r)
|
||||
goto fail0;
|
||||
|
||||
dss_clk_enable_all_no_ctx();
|
||||
|
||||
core.ctx_id = dss_get_ctx_id();
|
||||
DSSDBG("initial ctx id %u\n", core.ctx_id);
|
||||
|
||||
#ifdef CONFIG_FB_OMAP_BOOTLOADER_INIT
|
||||
/* DISPC_CONTROL */
|
||||
if (omap_readl(0x48050440) & 1) /* LCD enabled? */
|
||||
skip_init = 1;
|
||||
#endif
|
||||
|
||||
r = dss_init(skip_init);
|
||||
if (r) {
|
||||
DSSERR("Failed to initialize DSS\n");
|
||||
goto fail0;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_OMAP2_DSS_RFBI
|
||||
r = rfbi_init();
|
||||
if (r) {
|
||||
DSSERR("Failed to initialize rfbi\n");
|
||||
goto fail0;
|
||||
}
|
||||
#endif
|
||||
|
||||
r = dpi_init();
|
||||
if (r) {
|
||||
DSSERR("Failed to initialize dpi\n");
|
||||
goto fail0;
|
||||
}
|
||||
|
||||
r = dispc_init();
|
||||
if (r) {
|
||||
DSSERR("Failed to initialize dispc\n");
|
||||
goto fail0;
|
||||
}
|
||||
#ifdef CONFIG_OMAP2_DSS_VENC
|
||||
r = venc_init(pdev);
|
||||
if (r) {
|
||||
DSSERR("Failed to initialize venc\n");
|
||||
goto fail0;
|
||||
}
|
||||
#endif
|
||||
if (cpu_is_omap34xx()) {
|
||||
#ifdef CONFIG_OMAP2_DSS_SDI
|
||||
r = sdi_init(skip_init);
|
||||
if (r) {
|
||||
DSSERR("Failed to initialize SDI\n");
|
||||
goto fail0;
|
||||
}
|
||||
#endif
|
||||
#ifdef CONFIG_OMAP2_DSS_DSI
|
||||
r = dsi_init(pdev);
|
||||
if (r) {
|
||||
DSSERR("Failed to initialize DSI\n");
|
||||
goto fail0;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
#if defined(CONFIG_DEBUG_FS) && defined(CONFIG_OMAP2_DSS_DEBUG_SUPPORT)
|
||||
r = dss_initialize_debugfs();
|
||||
if (r)
|
||||
goto fail0;
|
||||
#endif
|
||||
|
||||
for (i = 0; i < pdata->num_devices; ++i) {
|
||||
struct omap_dss_device *dssdev = pdata->devices[i];
|
||||
|
||||
r = omap_dss_register_device(dssdev);
|
||||
if (r)
|
||||
DSSERR("device reg failed %d\n", i);
|
||||
|
||||
if (def_disp_name && strcmp(def_disp_name, dssdev->name) == 0)
|
||||
pdata->default_device = dssdev;
|
||||
}
|
||||
|
||||
dss_clk_disable_all();
|
||||
|
||||
return 0;
|
||||
|
||||
/* XXX fail correctly */
|
||||
fail0:
|
||||
return r;
|
||||
}
|
||||
|
||||
static int omap_dss_remove(struct platform_device *pdev)
|
||||
{
|
||||
struct omap_dss_board_info *pdata = pdev->dev.platform_data;
|
||||
int i;
|
||||
int c;
|
||||
|
||||
#if defined(CONFIG_DEBUG_FS) && defined(CONFIG_OMAP2_DSS_DEBUG_SUPPORT)
|
||||
dss_uninitialize_debugfs();
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_OMAP2_DSS_VENC
|
||||
venc_exit();
|
||||
#endif
|
||||
dispc_exit();
|
||||
dpi_exit();
|
||||
#ifdef CONFIG_OMAP2_DSS_RFBI
|
||||
rfbi_exit();
|
||||
#endif
|
||||
if (cpu_is_omap34xx()) {
|
||||
#ifdef CONFIG_OMAP2_DSS_DSI
|
||||
dsi_exit();
|
||||
#endif
|
||||
#ifdef CONFIG_OMAP2_DSS_SDI
|
||||
sdi_exit();
|
||||
#endif
|
||||
}
|
||||
|
||||
dss_exit();
|
||||
|
||||
/* these should be removed at some point */
|
||||
c = core.dss_ick->usecount;
|
||||
if (c > 0) {
|
||||
DSSERR("warning: dss_ick usecount %d, disabling\n", c);
|
||||
while (c-- > 0)
|
||||
clk_disable(core.dss_ick);
|
||||
}
|
||||
|
||||
c = core.dss1_fck->usecount;
|
||||
if (c > 0) {
|
||||
DSSERR("warning: dss1_fck usecount %d, disabling\n", c);
|
||||
while (c-- > 0)
|
||||
clk_disable(core.dss1_fck);
|
||||
}
|
||||
|
||||
c = core.dss2_fck->usecount;
|
||||
if (c > 0) {
|
||||
DSSERR("warning: dss2_fck usecount %d, disabling\n", c);
|
||||
while (c-- > 0)
|
||||
clk_disable(core.dss2_fck);
|
||||
}
|
||||
|
||||
c = core.dss_54m_fck->usecount;
|
||||
if (c > 0) {
|
||||
DSSERR("warning: dss_54m_fck usecount %d, disabling\n", c);
|
||||
while (c-- > 0)
|
||||
clk_disable(core.dss_54m_fck);
|
||||
}
|
||||
|
||||
if (core.dss_96m_fck) {
|
||||
c = core.dss_96m_fck->usecount;
|
||||
if (c > 0) {
|
||||
DSSERR("warning: dss_96m_fck usecount %d, disabling\n",
|
||||
c);
|
||||
while (c-- > 0)
|
||||
clk_disable(core.dss_96m_fck);
|
||||
}
|
||||
}
|
||||
|
||||
dss_put_clocks();
|
||||
|
||||
dss_uninit_overlays(pdev);
|
||||
dss_uninit_overlay_managers(pdev);
|
||||
|
||||
for (i = 0; i < pdata->num_devices; ++i)
|
||||
omap_dss_unregister_device(pdata->devices[i]);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void omap_dss_shutdown(struct platform_device *pdev)
|
||||
{
|
||||
DSSDBG("shutdown\n");
|
||||
dss_disable_all_devices();
|
||||
}
|
||||
|
||||
static int omap_dss_suspend(struct platform_device *pdev, pm_message_t state)
|
||||
{
|
||||
DSSDBG("suspend %d\n", state.event);
|
||||
|
||||
return dss_suspend_all_devices();
|
||||
}
|
||||
|
||||
static int omap_dss_resume(struct platform_device *pdev)
|
||||
{
|
||||
DSSDBG("resume\n");
|
||||
|
||||
return dss_resume_all_devices();
|
||||
}
|
||||
|
||||
static struct platform_driver omap_dss_driver = {
|
||||
.probe = omap_dss_probe,
|
||||
.remove = omap_dss_remove,
|
||||
.shutdown = omap_dss_shutdown,
|
||||
.suspend = omap_dss_suspend,
|
||||
.resume = omap_dss_resume,
|
||||
.driver = {
|
||||
.name = "omapdss",
|
||||
.owner = THIS_MODULE,
|
||||
},
|
||||
};
|
||||
|
||||
/* BUS */
|
||||
static int dss_bus_match(struct device *dev, struct device_driver *driver)
|
||||
{
|
||||
struct omap_dss_device *dssdev = to_dss_device(dev);
|
||||
|
||||
DSSDBG("bus_match. dev %s/%s, drv %s\n",
|
||||
dev_name(dev), dssdev->driver_name, driver->name);
|
||||
|
||||
return strcmp(dssdev->driver_name, driver->name) == 0;
|
||||
}
|
||||
|
||||
static ssize_t device_name_show(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
struct omap_dss_device *dssdev = to_dss_device(dev);
|
||||
return snprintf(buf, PAGE_SIZE, "%s\n",
|
||||
dssdev->name ?
|
||||
dssdev->name : "");
|
||||
}
|
||||
|
||||
static struct device_attribute default_dev_attrs[] = {
|
||||
__ATTR(name, S_IRUGO, device_name_show, NULL),
|
||||
__ATTR_NULL,
|
||||
};
|
||||
|
||||
static ssize_t driver_name_show(struct device_driver *drv, char *buf)
|
||||
{
|
||||
struct omap_dss_driver *dssdrv = to_dss_driver(drv);
|
||||
return snprintf(buf, PAGE_SIZE, "%s\n",
|
||||
dssdrv->driver.name ?
|
||||
dssdrv->driver.name : "");
|
||||
}
|
||||
static struct driver_attribute default_drv_attrs[] = {
|
||||
__ATTR(name, S_IRUGO, driver_name_show, NULL),
|
||||
__ATTR_NULL,
|
||||
};
|
||||
|
||||
static struct bus_type dss_bus_type = {
|
||||
.name = "omapdss",
|
||||
.match = dss_bus_match,
|
||||
.dev_attrs = default_dev_attrs,
|
||||
.drv_attrs = default_drv_attrs,
|
||||
};
|
||||
|
||||
static void dss_bus_release(struct device *dev)
|
||||
{
|
||||
DSSDBG("bus_release\n");
|
||||
}
|
||||
|
||||
static struct device dss_bus = {
|
||||
.release = dss_bus_release,
|
||||
};
|
||||
|
||||
struct bus_type *dss_get_bus(void)
|
||||
{
|
||||
return &dss_bus_type;
|
||||
}
|
||||
|
||||
/* DRIVER */
|
||||
static int dss_driver_probe(struct device *dev)
|
||||
{
|
||||
int r;
|
||||
struct omap_dss_driver *dssdrv = to_dss_driver(dev->driver);
|
||||
struct omap_dss_device *dssdev = to_dss_device(dev);
|
||||
struct omap_dss_board_info *pdata = core.pdev->dev.platform_data;
|
||||
bool force;
|
||||
|
||||
DSSDBG("driver_probe: dev %s/%s, drv %s\n",
|
||||
dev_name(dev), dssdev->driver_name,
|
||||
dssdrv->driver.name);
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
r = dssdrv->probe(dssdev);
|
||||
|
||||
if (r) {
|
||||
DSSERR("driver probe failed: %d\n", r);
|
||||
return r;
|
||||
}
|
||||
|
||||
DSSDBG("probe done for device %s\n", dev_name(dev));
|
||||
|
||||
dssdev->driver = dssdrv;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int dss_driver_remove(struct device *dev)
|
||||
{
|
||||
struct omap_dss_driver *dssdrv = to_dss_driver(dev->driver);
|
||||
struct omap_dss_device *dssdev = to_dss_device(dev);
|
||||
|
||||
DSSDBG("driver_remove: dev %s/%s\n", dev_name(dev),
|
||||
dssdev->driver_name);
|
||||
|
||||
dssdrv->remove(dssdev);
|
||||
|
||||
dss_uninit_device(core.pdev, dssdev);
|
||||
|
||||
dssdev->driver = NULL;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
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;
|
||||
return driver_register(&dssdriver->driver);
|
||||
}
|
||||
EXPORT_SYMBOL(omap_dss_register_driver);
|
||||
|
||||
void omap_dss_unregister_driver(struct omap_dss_driver *dssdriver)
|
||||
{
|
||||
driver_unregister(&dssdriver->driver);
|
||||
}
|
||||
EXPORT_SYMBOL(omap_dss_unregister_driver);
|
||||
|
||||
/* DEVICE */
|
||||
static void reset_device(struct device *dev, int check)
|
||||
{
|
||||
u8 *dev_p = (u8 *)dev;
|
||||
u8 *dev_end = dev_p + sizeof(*dev);
|
||||
void *saved_pdata;
|
||||
|
||||
saved_pdata = dev->platform_data;
|
||||
if (check) {
|
||||
/*
|
||||
* Check if there is any other setting than platform_data
|
||||
* in struct device; warn that these will be reset by our
|
||||
* init.
|
||||
*/
|
||||
dev->platform_data = NULL;
|
||||
while (dev_p < dev_end) {
|
||||
if (*dev_p) {
|
||||
WARN("%s: struct device fields will be "
|
||||
"discarded\n",
|
||||
__func__);
|
||||
break;
|
||||
}
|
||||
dev_p++;
|
||||
}
|
||||
}
|
||||
memset(dev, 0, sizeof(*dev));
|
||||
dev->platform_data = saved_pdata;
|
||||
}
|
||||
|
||||
|
||||
static void omap_dss_dev_release(struct device *dev)
|
||||
{
|
||||
reset_device(dev, 0);
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
reset_device(&dssdev->dev, 1);
|
||||
dssdev->dev.bus = &dss_bus_type;
|
||||
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;
|
||||
}
|
||||
|
||||
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 */
|
||||
static int omap_dss_bus_register(void)
|
||||
{
|
||||
int r;
|
||||
|
||||
r = bus_register(&dss_bus_type);
|
||||
if (r) {
|
||||
DSSERR("bus register failed\n");
|
||||
return r;
|
||||
}
|
||||
|
||||
dev_set_name(&dss_bus, "omapdss");
|
||||
r = device_register(&dss_bus);
|
||||
if (r) {
|
||||
DSSERR("bus driver register failed\n");
|
||||
bus_unregister(&dss_bus_type);
|
||||
return r;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* INIT */
|
||||
|
||||
#ifdef CONFIG_OMAP2_DSS_MODULE
|
||||
static void omap_dss_bus_unregister(void)
|
||||
{
|
||||
device_unregister(&dss_bus);
|
||||
|
||||
bus_unregister(&dss_bus_type);
|
||||
}
|
||||
|
||||
static int __init omap_dss_init(void)
|
||||
{
|
||||
int r;
|
||||
|
||||
r = omap_dss_bus_register();
|
||||
if (r)
|
||||
return r;
|
||||
|
||||
r = platform_driver_register(&omap_dss_driver);
|
||||
if (r) {
|
||||
omap_dss_bus_unregister();
|
||||
return r;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void __exit omap_dss_exit(void)
|
||||
{
|
||||
platform_driver_unregister(&omap_dss_driver);
|
||||
|
||||
omap_dss_bus_unregister();
|
||||
}
|
||||
|
||||
module_init(omap_dss_init);
|
||||
module_exit(omap_dss_exit);
|
||||
#else
|
||||
static int __init omap_dss_init(void)
|
||||
{
|
||||
return omap_dss_bus_register();
|
||||
}
|
||||
|
||||
static int __init omap_dss_init2(void)
|
||||
{
|
||||
return platform_driver_register(&omap_dss_driver);
|
||||
}
|
||||
|
||||
core_initcall(omap_dss_init);
|
||||
device_initcall(omap_dss_init2);
|
||||
#endif
|
||||
|
||||
MODULE_AUTHOR("Tomi Valkeinen <tomi.valkeinen@nokia.com>");
|
||||
MODULE_DESCRIPTION("OMAP2/3 Display Subsystem");
|
||||
MODULE_LICENSE("GPL v2");
|
||||
|
596
drivers/video/omap2/dss/dss.c
Normal file
596
drivers/video/omap2/dss/dss.c
Normal file
@ -0,0 +1,596 @@
|
||||
/*
|
||||
* linux/drivers/video/omap2/dss/dss.c
|
||||
*
|
||||
* Copyright (C) 2009 Nokia Corporation
|
||||
* Author: Tomi Valkeinen <tomi.valkeinen@nokia.com>
|
||||
*
|
||||
* Some code and ideas taken from drivers/video/omap/ driver
|
||||
* by Imre Deak.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 as published by
|
||||
* the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
* more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with
|
||||
* this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#define DSS_SUBSYS_NAME "DSS"
|
||||
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/err.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/seq_file.h>
|
||||
#include <linux/clk.h>
|
||||
|
||||
#include <plat/display.h>
|
||||
#include "dss.h"
|
||||
|
||||
#define DSS_BASE 0x48050000
|
||||
|
||||
#define DSS_SZ_REGS SZ_512
|
||||
|
||||
struct dss_reg {
|
||||
u16 idx;
|
||||
};
|
||||
|
||||
#define DSS_REG(idx) ((const struct dss_reg) { idx })
|
||||
|
||||
#define DSS_REVISION DSS_REG(0x0000)
|
||||
#define DSS_SYSCONFIG DSS_REG(0x0010)
|
||||
#define DSS_SYSSTATUS DSS_REG(0x0014)
|
||||
#define DSS_IRQSTATUS DSS_REG(0x0018)
|
||||
#define DSS_CONTROL DSS_REG(0x0040)
|
||||
#define DSS_SDI_CONTROL DSS_REG(0x0044)
|
||||
#define DSS_PLL_CONTROL DSS_REG(0x0048)
|
||||
#define DSS_SDI_STATUS DSS_REG(0x005C)
|
||||
|
||||
#define REG_GET(idx, start, end) \
|
||||
FLD_GET(dss_read_reg(idx), start, end)
|
||||
|
||||
#define REG_FLD_MOD(idx, val, start, end) \
|
||||
dss_write_reg(idx, FLD_MOD(dss_read_reg(idx), val, start, end))
|
||||
|
||||
static struct {
|
||||
void __iomem *base;
|
||||
|
||||
struct clk *dpll4_m4_ck;
|
||||
|
||||
unsigned long cache_req_pck;
|
||||
unsigned long cache_prate;
|
||||
struct dss_clock_info cache_dss_cinfo;
|
||||
struct dispc_clock_info cache_dispc_cinfo;
|
||||
|
||||
u32 ctx[DSS_SZ_REGS / sizeof(u32)];
|
||||
} dss;
|
||||
|
||||
static int _omap_dss_wait_reset(void);
|
||||
|
||||
static inline void dss_write_reg(const struct dss_reg idx, u32 val)
|
||||
{
|
||||
__raw_writel(val, dss.base + idx.idx);
|
||||
}
|
||||
|
||||
static inline u32 dss_read_reg(const struct dss_reg idx)
|
||||
{
|
||||
return __raw_readl(dss.base + idx.idx);
|
||||
}
|
||||
|
||||
#define SR(reg) \
|
||||
dss.ctx[(DSS_##reg).idx / sizeof(u32)] = dss_read_reg(DSS_##reg)
|
||||
#define RR(reg) \
|
||||
dss_write_reg(DSS_##reg, dss.ctx[(DSS_##reg).idx / sizeof(u32)])
|
||||
|
||||
void dss_save_context(void)
|
||||
{
|
||||
if (cpu_is_omap24xx())
|
||||
return;
|
||||
|
||||
SR(SYSCONFIG);
|
||||
SR(CONTROL);
|
||||
|
||||
#ifdef CONFIG_OMAP2_DSS_SDI
|
||||
SR(SDI_CONTROL);
|
||||
SR(PLL_CONTROL);
|
||||
#endif
|
||||
}
|
||||
|
||||
void dss_restore_context(void)
|
||||
{
|
||||
if (_omap_dss_wait_reset())
|
||||
DSSERR("DSS not coming out of reset after sleep\n");
|
||||
|
||||
RR(SYSCONFIG);
|
||||
RR(CONTROL);
|
||||
|
||||
#ifdef CONFIG_OMAP2_DSS_SDI
|
||||
RR(SDI_CONTROL);
|
||||
RR(PLL_CONTROL);
|
||||
#endif
|
||||
}
|
||||
|
||||
#undef SR
|
||||
#undef RR
|
||||
|
||||
void dss_sdi_init(u8 datapairs)
|
||||
{
|
||||
u32 l;
|
||||
|
||||
BUG_ON(datapairs > 3 || datapairs < 1);
|
||||
|
||||
l = dss_read_reg(DSS_SDI_CONTROL);
|
||||
l = FLD_MOD(l, 0xf, 19, 15); /* SDI_PDIV */
|
||||
l = FLD_MOD(l, datapairs-1, 3, 2); /* SDI_PRSEL */
|
||||
l = FLD_MOD(l, 2, 1, 0); /* SDI_BWSEL */
|
||||
dss_write_reg(DSS_SDI_CONTROL, l);
|
||||
|
||||
l = dss_read_reg(DSS_PLL_CONTROL);
|
||||
l = FLD_MOD(l, 0x7, 25, 22); /* SDI_PLL_FREQSEL */
|
||||
l = FLD_MOD(l, 0xb, 16, 11); /* SDI_PLL_REGN */
|
||||
l = FLD_MOD(l, 0xb4, 10, 1); /* SDI_PLL_REGM */
|
||||
dss_write_reg(DSS_PLL_CONTROL, l);
|
||||
}
|
||||
|
||||
int dss_sdi_enable(void)
|
||||
{
|
||||
unsigned long timeout;
|
||||
|
||||
dispc_pck_free_enable(1);
|
||||
|
||||
/* Reset SDI PLL */
|
||||
REG_FLD_MOD(DSS_PLL_CONTROL, 1, 18, 18); /* SDI_PLL_SYSRESET */
|
||||
udelay(1); /* wait 2x PCLK */
|
||||
|
||||
/* Lock SDI PLL */
|
||||
REG_FLD_MOD(DSS_PLL_CONTROL, 1, 28, 28); /* SDI_PLL_GOBIT */
|
||||
|
||||
/* Waiting for PLL lock request to complete */
|
||||
timeout = jiffies + msecs_to_jiffies(500);
|
||||
while (dss_read_reg(DSS_SDI_STATUS) & (1 << 6)) {
|
||||
if (time_after_eq(jiffies, timeout)) {
|
||||
DSSERR("PLL lock request timed out\n");
|
||||
goto err1;
|
||||
}
|
||||
}
|
||||
|
||||
/* Clearing PLL_GO bit */
|
||||
REG_FLD_MOD(DSS_PLL_CONTROL, 0, 28, 28);
|
||||
|
||||
/* Waiting for PLL to lock */
|
||||
timeout = jiffies + msecs_to_jiffies(500);
|
||||
while (!(dss_read_reg(DSS_SDI_STATUS) & (1 << 5))) {
|
||||
if (time_after_eq(jiffies, timeout)) {
|
||||
DSSERR("PLL lock timed out\n");
|
||||
goto err1;
|
||||
}
|
||||
}
|
||||
|
||||
dispc_lcd_enable_signal(1);
|
||||
|
||||
/* Waiting for SDI reset to complete */
|
||||
timeout = jiffies + msecs_to_jiffies(500);
|
||||
while (!(dss_read_reg(DSS_SDI_STATUS) & (1 << 2))) {
|
||||
if (time_after_eq(jiffies, timeout)) {
|
||||
DSSERR("SDI reset timed out\n");
|
||||
goto err2;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
err2:
|
||||
dispc_lcd_enable_signal(0);
|
||||
err1:
|
||||
/* Reset SDI PLL */
|
||||
REG_FLD_MOD(DSS_PLL_CONTROL, 0, 18, 18); /* SDI_PLL_SYSRESET */
|
||||
|
||||
dispc_pck_free_enable(0);
|
||||
|
||||
return -ETIMEDOUT;
|
||||
}
|
||||
|
||||
void dss_sdi_disable(void)
|
||||
{
|
||||
dispc_lcd_enable_signal(0);
|
||||
|
||||
dispc_pck_free_enable(0);
|
||||
|
||||
/* Reset SDI PLL */
|
||||
REG_FLD_MOD(DSS_PLL_CONTROL, 0, 18, 18); /* SDI_PLL_SYSRESET */
|
||||
}
|
||||
|
||||
void dss_dump_clocks(struct seq_file *s)
|
||||
{
|
||||
unsigned long dpll4_ck_rate;
|
||||
unsigned long dpll4_m4_ck_rate;
|
||||
|
||||
dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK1);
|
||||
|
||||
dpll4_ck_rate = clk_get_rate(clk_get_parent(dss.dpll4_m4_ck));
|
||||
dpll4_m4_ck_rate = clk_get_rate(dss.dpll4_m4_ck);
|
||||
|
||||
seq_printf(s, "- DSS -\n");
|
||||
|
||||
seq_printf(s, "dpll4_ck %lu\n", dpll4_ck_rate);
|
||||
|
||||
seq_printf(s, "dss1_alwon_fclk = %lu / %lu * 2 = %lu\n",
|
||||
dpll4_ck_rate,
|
||||
dpll4_ck_rate / dpll4_m4_ck_rate,
|
||||
dss_clk_get_rate(DSS_CLK_FCK1));
|
||||
|
||||
dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK1);
|
||||
}
|
||||
|
||||
void dss_dump_regs(struct seq_file *s)
|
||||
{
|
||||
#define DUMPREG(r) seq_printf(s, "%-35s %08x\n", #r, dss_read_reg(r))
|
||||
|
||||
dss_clk_enable(DSS_CLK_ICK | DSS_CLK_FCK1);
|
||||
|
||||
DUMPREG(DSS_REVISION);
|
||||
DUMPREG(DSS_SYSCONFIG);
|
||||
DUMPREG(DSS_SYSSTATUS);
|
||||
DUMPREG(DSS_IRQSTATUS);
|
||||
DUMPREG(DSS_CONTROL);
|
||||
DUMPREG(DSS_SDI_CONTROL);
|
||||
DUMPREG(DSS_PLL_CONTROL);
|
||||
DUMPREG(DSS_SDI_STATUS);
|
||||
|
||||
dss_clk_disable(DSS_CLK_ICK | DSS_CLK_FCK1);
|
||||
#undef DUMPREG
|
||||
}
|
||||
|
||||
void dss_select_clk_source(bool dsi, bool dispc)
|
||||
{
|
||||
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 dss_get_dsi_clk_source(void)
|
||||
{
|
||||
return FLD_GET(dss_read_reg(DSS_CONTROL), 1, 1);
|
||||
}
|
||||
|
||||
int dss_get_dispc_clk_source(void)
|
||||
{
|
||||
return FLD_GET(dss_read_reg(DSS_CONTROL), 0, 0);
|
||||
}
|
||||
|
||||
/* calculate clock rates using dividers in cinfo */
|
||||
int dss_calc_clock_rates(struct dss_clock_info *cinfo)
|
||||
{
|
||||
unsigned long prate;
|
||||
|
||||
if (cinfo->fck_div > 16 || cinfo->fck_div == 0)
|
||||
return -EINVAL;
|
||||
|
||||
prate = clk_get_rate(clk_get_parent(dss.dpll4_m4_ck));
|
||||
|
||||
cinfo->fck = prate / cinfo->fck_div;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int dss_set_clock_div(struct dss_clock_info *cinfo)
|
||||
{
|
||||
unsigned long prate;
|
||||
int r;
|
||||
|
||||
if (cpu_is_omap34xx()) {
|
||||
prate = clk_get_rate(clk_get_parent(dss.dpll4_m4_ck));
|
||||
DSSDBG("dpll4_m4 = %ld\n", prate);
|
||||
|
||||
r = clk_set_rate(dss.dpll4_m4_ck, prate / cinfo->fck_div);
|
||||
if (r)
|
||||
return r;
|
||||
}
|
||||
|
||||
DSSDBG("fck = %ld (%d)\n", cinfo->fck, cinfo->fck_div);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int dss_get_clock_div(struct dss_clock_info *cinfo)
|
||||
{
|
||||
cinfo->fck = dss_clk_get_rate(DSS_CLK_FCK1);
|
||||
|
||||
if (cpu_is_omap34xx()) {
|
||||
unsigned long prate;
|
||||
prate = clk_get_rate(clk_get_parent(dss.dpll4_m4_ck));
|
||||
cinfo->fck_div = prate / (cinfo->fck / 2);
|
||||
} else {
|
||||
cinfo->fck_div = 0;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
unsigned long dss_get_dpll4_rate(void)
|
||||
{
|
||||
if (cpu_is_omap34xx())
|
||||
return clk_get_rate(clk_get_parent(dss.dpll4_m4_ck));
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
int dss_calc_clock_div(bool is_tft, unsigned long req_pck,
|
||||
struct dss_clock_info *dss_cinfo,
|
||||
struct dispc_clock_info *dispc_cinfo)
|
||||
{
|
||||
unsigned long prate;
|
||||
struct dss_clock_info best_dss;
|
||||
struct dispc_clock_info best_dispc;
|
||||
|
||||
unsigned long fck;
|
||||
|
||||
u16 fck_div;
|
||||
|
||||
int match = 0;
|
||||
int min_fck_per_pck;
|
||||
|
||||
prate = dss_get_dpll4_rate();
|
||||
|
||||
fck = dss_clk_get_rate(DSS_CLK_FCK1);
|
||||
if (req_pck == dss.cache_req_pck &&
|
||||
((cpu_is_omap34xx() && prate == dss.cache_prate) ||
|
||||
dss.cache_dss_cinfo.fck == fck)) {
|
||||
DSSDBG("dispc clock info found from cache.\n");
|
||||
*dss_cinfo = dss.cache_dss_cinfo;
|
||||
*dispc_cinfo = dss.cache_dispc_cinfo;
|
||||
return 0;
|
||||
}
|
||||
|
||||
min_fck_per_pck = CONFIG_OMAP2_DSS_MIN_FCK_PER_PCK;
|
||||
|
||||
if (min_fck_per_pck &&
|
||||
req_pck * min_fck_per_pck > DISPC_MAX_FCK) {
|
||||
DSSERR("Requested pixel clock not possible with the current "
|
||||
"OMAP2_DSS_MIN_FCK_PER_PCK setting. Turning "
|
||||
"the constraint off.\n");
|
||||
min_fck_per_pck = 0;
|
||||
}
|
||||
|
||||
retry:
|
||||
memset(&best_dss, 0, sizeof(best_dss));
|
||||
memset(&best_dispc, 0, sizeof(best_dispc));
|
||||
|
||||
if (cpu_is_omap24xx()) {
|
||||
struct dispc_clock_info cur_dispc;
|
||||
/* XXX can we change the clock on omap2? */
|
||||
fck = dss_clk_get_rate(DSS_CLK_FCK1);
|
||||
fck_div = 1;
|
||||
|
||||
dispc_find_clk_divs(is_tft, req_pck, fck, &cur_dispc);
|
||||
match = 1;
|
||||
|
||||
best_dss.fck = fck;
|
||||
best_dss.fck_div = fck_div;
|
||||
|
||||
best_dispc = cur_dispc;
|
||||
|
||||
goto found;
|
||||
} else if (cpu_is_omap34xx()) {
|
||||
for (fck_div = 16; fck_div > 0; --fck_div) {
|
||||
struct dispc_clock_info cur_dispc;
|
||||
|
||||
fck = prate / fck_div * 2;
|
||||
|
||||
if (fck > DISPC_MAX_FCK)
|
||||
continue;
|
||||
|
||||
if (min_fck_per_pck &&
|
||||
fck < req_pck * min_fck_per_pck)
|
||||
continue;
|
||||
|
||||
match = 1;
|
||||
|
||||
dispc_find_clk_divs(is_tft, req_pck, fck, &cur_dispc);
|
||||
|
||||
if (abs(cur_dispc.pck - req_pck) <
|
||||
abs(best_dispc.pck - req_pck)) {
|
||||
|
||||
best_dss.fck = fck;
|
||||
best_dss.fck_div = fck_div;
|
||||
|
||||
best_dispc = cur_dispc;
|
||||
|
||||
if (cur_dispc.pck == req_pck)
|
||||
goto found;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
BUG();
|
||||
}
|
||||
|
||||
found:
|
||||
if (!match) {
|
||||
if (min_fck_per_pck) {
|
||||
DSSERR("Could not find suitable clock settings.\n"
|
||||
"Turning FCK/PCK constraint off and"
|
||||
"trying again.\n");
|
||||
min_fck_per_pck = 0;
|
||||
goto retry;
|
||||
}
|
||||
|
||||
DSSERR("Could not find suitable clock settings.\n");
|
||||
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (dss_cinfo)
|
||||
*dss_cinfo = best_dss;
|
||||
if (dispc_cinfo)
|
||||
*dispc_cinfo = best_dispc;
|
||||
|
||||
dss.cache_req_pck = req_pck;
|
||||
dss.cache_prate = prate;
|
||||
dss.cache_dss_cinfo = best_dss;
|
||||
dss.cache_dispc_cinfo = best_dispc;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
static irqreturn_t dss_irq_handler_omap2(int irq, void *arg)
|
||||
{
|
||||
dispc_irq_handler();
|
||||
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
static irqreturn_t dss_irq_handler_omap3(int irq, void *arg)
|
||||
{
|
||||
u32 irqstatus;
|
||||
|
||||
irqstatus = dss_read_reg(DSS_IRQSTATUS);
|
||||
|
||||
if (irqstatus & (1<<0)) /* DISPC_IRQ */
|
||||
dispc_irq_handler();
|
||||
#ifdef CONFIG_OMAP2_DSS_DSI
|
||||
if (irqstatus & (1<<1)) /* DSI_IRQ */
|
||||
dsi_irq_handler();
|
||||
#endif
|
||||
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
static int _omap_dss_wait_reset(void)
|
||||
{
|
||||
unsigned timeout = 1000;
|
||||
|
||||
while (REG_GET(DSS_SYSSTATUS, 0, 0) == 0) {
|
||||
udelay(1);
|
||||
if (!--timeout) {
|
||||
DSSERR("soft reset failed\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int _omap_dss_reset(void)
|
||||
{
|
||||
/* Soft reset */
|
||||
REG_FLD_MOD(DSS_SYSCONFIG, 1, 1, 1);
|
||||
return _omap_dss_wait_reset();
|
||||
}
|
||||
|
||||
void dss_set_venc_output(enum omap_dss_venc_type type)
|
||||
{
|
||||
int l = 0;
|
||||
|
||||
if (type == OMAP_DSS_VENC_TYPE_COMPOSITE)
|
||||
l = 0;
|
||||
else if (type == OMAP_DSS_VENC_TYPE_SVIDEO)
|
||||
l = 1;
|
||||
else
|
||||
BUG();
|
||||
|
||||
/* venc out selection. 0 = comp, 1 = svideo */
|
||||
REG_FLD_MOD(DSS_CONTROL, l, 6, 6);
|
||||
}
|
||||
|
||||
void dss_set_dac_pwrdn_bgz(bool enable)
|
||||
{
|
||||
REG_FLD_MOD(DSS_CONTROL, enable, 5, 5); /* DAC Power-Down Control */
|
||||
}
|
||||
|
||||
int dss_init(bool skip_init)
|
||||
{
|
||||
int r;
|
||||
u32 rev;
|
||||
|
||||
dss.base = ioremap(DSS_BASE, DSS_SZ_REGS);
|
||||
if (!dss.base) {
|
||||
DSSERR("can't ioremap DSS\n");
|
||||
r = -ENOMEM;
|
||||
goto fail0;
|
||||
}
|
||||
|
||||
if (!skip_init) {
|
||||
/* disable LCD and DIGIT output. This seems to fix the synclost
|
||||
* problem that we get, if the bootloader starts the DSS and
|
||||
* the kernel resets it */
|
||||
omap_writel(omap_readl(0x48050440) & ~0x3, 0x48050440);
|
||||
|
||||
/* We need to wait here a bit, otherwise we sometimes start to
|
||||
* get synclost errors, and after that only power cycle will
|
||||
* restore DSS functionality. I have no idea why this happens.
|
||||
* And we have to wait _before_ resetting the DSS, but after
|
||||
* enabling clocks.
|
||||
*/
|
||||
msleep(50);
|
||||
|
||||
_omap_dss_reset();
|
||||
}
|
||||
|
||||
/* autoidle */
|
||||
REG_FLD_MOD(DSS_SYSCONFIG, 1, 0, 0);
|
||||
|
||||
/* Select DPLL */
|
||||
REG_FLD_MOD(DSS_CONTROL, 0, 0, 0);
|
||||
|
||||
#ifdef CONFIG_OMAP2_DSS_VENC
|
||||
REG_FLD_MOD(DSS_CONTROL, 1, 4, 4); /* venc dac demen */
|
||||
REG_FLD_MOD(DSS_CONTROL, 1, 3, 3); /* venc clock 4x enable */
|
||||
REG_FLD_MOD(DSS_CONTROL, 0, 2, 2); /* venc clock mode = normal */
|
||||
#endif
|
||||
|
||||
r = request_irq(INT_24XX_DSS_IRQ,
|
||||
cpu_is_omap24xx()
|
||||
? dss_irq_handler_omap2
|
||||
: dss_irq_handler_omap3,
|
||||
0, "OMAP DSS", NULL);
|
||||
|
||||
if (r < 0) {
|
||||
DSSERR("omap2 dss: request_irq failed\n");
|
||||
goto fail1;
|
||||
}
|
||||
|
||||
if (cpu_is_omap34xx()) {
|
||||
dss.dpll4_m4_ck = clk_get(NULL, "dpll4_m4_ck");
|
||||
if (IS_ERR(dss.dpll4_m4_ck)) {
|
||||
DSSERR("Failed to get dpll4_m4_ck\n");
|
||||
r = PTR_ERR(dss.dpll4_m4_ck);
|
||||
goto fail2;
|
||||
}
|
||||
}
|
||||
|
||||
dss_save_context();
|
||||
|
||||
rev = dss_read_reg(DSS_REVISION);
|
||||
printk(KERN_INFO "OMAP DSS rev %d.%d\n",
|
||||
FLD_GET(rev, 7, 4), FLD_GET(rev, 3, 0));
|
||||
|
||||
return 0;
|
||||
|
||||
fail2:
|
||||
free_irq(INT_24XX_DSS_IRQ, NULL);
|
||||
fail1:
|
||||
iounmap(dss.base);
|
||||
fail0:
|
||||
return r;
|
||||
}
|
||||
|
||||
void dss_exit(void)
|
||||
{
|
||||
if (cpu_is_omap34xx())
|
||||
clk_put(dss.dpll4_m4_ck);
|
||||
|
||||
free_irq(INT_24XX_DSS_IRQ, NULL);
|
||||
|
||||
iounmap(dss.base);
|
||||
}
|
||||
|
370
drivers/video/omap2/dss/dss.h
Normal file
370
drivers/video/omap2/dss/dss.h
Normal file
@ -0,0 +1,370 @@
|
||||
/*
|
||||
* linux/drivers/video/omap2/dss/dss.h
|
||||
*
|
||||
* Copyright (C) 2009 Nokia Corporation
|
||||
* Author: Tomi Valkeinen <tomi.valkeinen@nokia.com>
|
||||
*
|
||||
* Some code and ideas taken from drivers/video/omap/ driver
|
||||
* by Imre Deak.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 as published by
|
||||
* the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
* more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with
|
||||
* this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef __OMAP2_DSS_H
|
||||
#define __OMAP2_DSS_H
|
||||
|
||||
#ifdef CONFIG_OMAP2_DSS_DEBUG_SUPPORT
|
||||
#define DEBUG
|
||||
#endif
|
||||
|
||||
#ifdef DEBUG
|
||||
extern unsigned int dss_debug;
|
||||
#ifdef DSS_SUBSYS_NAME
|
||||
#define DSSDBG(format, ...) \
|
||||
if (dss_debug) \
|
||||
printk(KERN_DEBUG "omapdss " DSS_SUBSYS_NAME ": " format, \
|
||||
## __VA_ARGS__)
|
||||
#else
|
||||
#define DSSDBG(format, ...) \
|
||||
if (dss_debug) \
|
||||
printk(KERN_DEBUG "omapdss: " format, ## __VA_ARGS__)
|
||||
#endif
|
||||
|
||||
#ifdef DSS_SUBSYS_NAME
|
||||
#define DSSDBGF(format, ...) \
|
||||
if (dss_debug) \
|
||||
printk(KERN_DEBUG "omapdss " DSS_SUBSYS_NAME \
|
||||
": %s(" format ")\n", \
|
||||
__func__, \
|
||||
## __VA_ARGS__)
|
||||
#else
|
||||
#define DSSDBGF(format, ...) \
|
||||
if (dss_debug) \
|
||||
printk(KERN_DEBUG "omapdss: " \
|
||||
": %s(" format ")\n", \
|
||||
__func__, \
|
||||
## __VA_ARGS__)
|
||||
#endif
|
||||
|
||||
#else /* DEBUG */
|
||||
#define DSSDBG(format, ...)
|
||||
#define DSSDBGF(format, ...)
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef DSS_SUBSYS_NAME
|
||||
#define DSSERR(format, ...) \
|
||||
printk(KERN_ERR "omapdss " DSS_SUBSYS_NAME " error: " format, \
|
||||
## __VA_ARGS__)
|
||||
#else
|
||||
#define DSSERR(format, ...) \
|
||||
printk(KERN_ERR "omapdss error: " format, ## __VA_ARGS__)
|
||||
#endif
|
||||
|
||||
#ifdef DSS_SUBSYS_NAME
|
||||
#define DSSINFO(format, ...) \
|
||||
printk(KERN_INFO "omapdss " DSS_SUBSYS_NAME ": " format, \
|
||||
## __VA_ARGS__)
|
||||
#else
|
||||
#define DSSINFO(format, ...) \
|
||||
printk(KERN_INFO "omapdss: " format, ## __VA_ARGS__)
|
||||
#endif
|
||||
|
||||
#ifdef DSS_SUBSYS_NAME
|
||||
#define DSSWARN(format, ...) \
|
||||
printk(KERN_WARNING "omapdss " DSS_SUBSYS_NAME ": " format, \
|
||||
## __VA_ARGS__)
|
||||
#else
|
||||
#define DSSWARN(format, ...) \
|
||||
printk(KERN_WARNING "omapdss: " format, ## __VA_ARGS__)
|
||||
#endif
|
||||
|
||||
/* OMAP TRM gives bitfields as start:end, where start is the higher bit
|
||||
number. For example 7:0 */
|
||||
#define FLD_MASK(start, end) (((1 << ((start) - (end) + 1)) - 1) << (end))
|
||||
#define FLD_VAL(val, start, end) (((val) << (end)) & FLD_MASK(start, end))
|
||||
#define FLD_GET(val, start, end) (((val) & FLD_MASK(start, end)) >> (end))
|
||||
#define FLD_MOD(orig, val, start, end) \
|
||||
(((orig) & ~FLD_MASK(start, end)) | FLD_VAL(val, start, end))
|
||||
|
||||
#define DISPC_MAX_FCK 173000000
|
||||
|
||||
enum omap_burst_size {
|
||||
OMAP_DSS_BURST_4x32 = 0,
|
||||
OMAP_DSS_BURST_8x32 = 1,
|
||||
OMAP_DSS_BURST_16x32 = 2,
|
||||
};
|
||||
|
||||
enum omap_parallel_interface_mode {
|
||||
OMAP_DSS_PARALLELMODE_BYPASS, /* MIPI DPI */
|
||||
OMAP_DSS_PARALLELMODE_RFBI, /* MIPI DBI */
|
||||
OMAP_DSS_PARALLELMODE_DSI,
|
||||
};
|
||||
|
||||
enum dss_clock {
|
||||
DSS_CLK_ICK = 1 << 0,
|
||||
DSS_CLK_FCK1 = 1 << 1,
|
||||
DSS_CLK_FCK2 = 1 << 2,
|
||||
DSS_CLK_54M = 1 << 3,
|
||||
DSS_CLK_96M = 1 << 4,
|
||||
};
|
||||
|
||||
struct dss_clock_info {
|
||||
/* rates that we get with dividers below */
|
||||
unsigned long fck;
|
||||
|
||||
/* dividers */
|
||||
u16 fck_div;
|
||||
};
|
||||
|
||||
struct dispc_clock_info {
|
||||
/* rates that we get with dividers below */
|
||||
unsigned long lck;
|
||||
unsigned long pck;
|
||||
|
||||
/* dividers */
|
||||
u16 lck_div;
|
||||
u16 pck_div;
|
||||
};
|
||||
|
||||
struct dsi_clock_info {
|
||||
/* rates that we get with dividers below */
|
||||
unsigned long fint;
|
||||
unsigned long clkin4ddr;
|
||||
unsigned long clkin;
|
||||
unsigned long dsi1_pll_fclk;
|
||||
unsigned long dsi2_pll_fclk;
|
||||
|
||||
unsigned long lp_clk;
|
||||
|
||||
/* dividers */
|
||||
u16 regn;
|
||||
u16 regm;
|
||||
u16 regm3;
|
||||
u16 regm4;
|
||||
|
||||
u16 lp_clk_div;
|
||||
|
||||
u8 highfreq;
|
||||
bool use_dss2_fck;
|
||||
};
|
||||
|
||||
struct seq_file;
|
||||
struct platform_device;
|
||||
|
||||
/* core */
|
||||
void dss_clk_enable(enum dss_clock clks);
|
||||
void dss_clk_disable(enum dss_clock clks);
|
||||
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);
|
||||
|
||||
/* display */
|
||||
int dss_suspend_all_devices(void);
|
||||
int dss_resume_all_devices(void);
|
||||
void dss_disable_all_devices(void);
|
||||
|
||||
void dss_init_device(struct platform_device *pdev,
|
||||
struct omap_dss_device *dssdev);
|
||||
void dss_uninit_device(struct platform_device *pdev,
|
||||
struct omap_dss_device *dssdev);
|
||||
bool dss_use_replication(struct omap_dss_device *dssdev,
|
||||
enum omap_color_mode mode);
|
||||
void default_get_overlay_fifo_thresholds(enum omap_plane plane,
|
||||
u32 fifo_size, enum omap_burst_size *burst_size,
|
||||
u32 *fifo_low, u32 *fifo_high);
|
||||
|
||||
/* manager */
|
||||
int dss_init_overlay_managers(struct platform_device *pdev);
|
||||
void dss_uninit_overlay_managers(struct platform_device *pdev);
|
||||
int dss_mgr_wait_for_go_ovl(struct omap_overlay *ovl);
|
||||
void dss_setup_partial_planes(struct omap_dss_device *dssdev,
|
||||
u16 *x, u16 *y, u16 *w, u16 *h);
|
||||
void dss_start_update(struct omap_dss_device *dssdev);
|
||||
|
||||
/* overlay */
|
||||
void dss_init_overlays(struct platform_device *pdev);
|
||||
void dss_uninit_overlays(struct platform_device *pdev);
|
||||
int dss_check_overlay(struct omap_overlay *ovl, struct omap_dss_device *dssdev);
|
||||
void dss_overlay_setup_dispc_manager(struct omap_overlay_manager *mgr);
|
||||
#ifdef L4_EXAMPLE
|
||||
void dss_overlay_setup_l4_manager(struct omap_overlay_manager *mgr);
|
||||
#endif
|
||||
void dss_recheck_connections(struct omap_dss_device *dssdev, bool force);
|
||||
|
||||
/* DSS */
|
||||
int dss_init(bool skip_init);
|
||||
void dss_exit(void);
|
||||
|
||||
void dss_save_context(void);
|
||||
void dss_restore_context(void);
|
||||
|
||||
void dss_dump_regs(struct seq_file *s);
|
||||
|
||||
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_set_venc_output(enum omap_dss_venc_type type);
|
||||
void dss_set_dac_pwrdn_bgz(bool enable);
|
||||
|
||||
unsigned long dss_get_dpll4_rate(void);
|
||||
int dss_calc_clock_rates(struct dss_clock_info *cinfo);
|
||||
int dss_set_clock_div(struct dss_clock_info *cinfo);
|
||||
int dss_get_clock_div(struct dss_clock_info *cinfo);
|
||||
int dss_calc_clock_div(bool is_tft, unsigned long req_pck,
|
||||
struct dss_clock_info *dss_cinfo,
|
||||
struct dispc_clock_info *dispc_cinfo);
|
||||
|
||||
/* SDI */
|
||||
int sdi_init(bool skip_init);
|
||||
void sdi_exit(void);
|
||||
int sdi_init_display(struct omap_dss_device *display);
|
||||
|
||||
/* DSI */
|
||||
int dsi_init(struct platform_device *pdev);
|
||||
void dsi_exit(void);
|
||||
|
||||
void dsi_dump_clocks(struct seq_file *s);
|
||||
void dsi_dump_regs(struct seq_file *s);
|
||||
|
||||
void dsi_save_context(void);
|
||||
void dsi_restore_context(void);
|
||||
|
||||
int dsi_init_display(struct omap_dss_device *display);
|
||||
void dsi_irq_handler(void);
|
||||
unsigned long dsi_get_dsi1_pll_rate(void);
|
||||
int dsi_pll_set_clock_div(struct dsi_clock_info *cinfo);
|
||||
int dsi_pll_calc_clock_div_pck(bool is_tft, unsigned long req_pck,
|
||||
struct dsi_clock_info *cinfo,
|
||||
struct dispc_clock_info *dispc_cinfo);
|
||||
int dsi_pll_init(struct omap_dss_device *dssdev, bool enable_hsclk,
|
||||
bool enable_hsdiv);
|
||||
void dsi_pll_uninit(void);
|
||||
void dsi_get_overlay_fifo_thresholds(enum omap_plane plane,
|
||||
u32 fifo_size, enum omap_burst_size *burst_size,
|
||||
u32 *fifo_low, u32 *fifo_high);
|
||||
|
||||
/* DPI */
|
||||
int dpi_init(void);
|
||||
void dpi_exit(void);
|
||||
int dpi_init_display(struct omap_dss_device *dssdev);
|
||||
|
||||
/* DISPC */
|
||||
int dispc_init(void);
|
||||
void dispc_exit(void);
|
||||
void dispc_dump_clocks(struct seq_file *s);
|
||||
void dispc_dump_regs(struct seq_file *s);
|
||||
void dispc_irq_handler(void);
|
||||
void dispc_fake_vsync_irq(void);
|
||||
|
||||
void dispc_save_context(void);
|
||||
void dispc_restore_context(void);
|
||||
|
||||
void dispc_enable_sidle(void);
|
||||
void dispc_disable_sidle(void);
|
||||
|
||||
void dispc_lcd_enable_signal_polarity(bool act_high);
|
||||
void dispc_lcd_enable_signal(bool enable);
|
||||
void dispc_pck_free_enable(bool enable);
|
||||
void dispc_enable_fifohandcheck(bool enable);
|
||||
|
||||
void dispc_set_lcd_size(u16 width, u16 height);
|
||||
void dispc_set_digit_size(u16 width, u16 height);
|
||||
u32 dispc_get_plane_fifo_size(enum omap_plane plane);
|
||||
void dispc_setup_plane_fifo(enum omap_plane plane, u32 low, u32 high);
|
||||
void dispc_enable_fifomerge(bool enable);
|
||||
void dispc_set_burst_size(enum omap_plane plane,
|
||||
enum omap_burst_size burst_size);
|
||||
|
||||
void dispc_set_plane_ba0(enum omap_plane plane, u32 paddr);
|
||||
void dispc_set_plane_ba1(enum omap_plane plane, u32 paddr);
|
||||
void dispc_set_plane_pos(enum omap_plane plane, u16 x, u16 y);
|
||||
void dispc_set_plane_size(enum omap_plane plane, u16 width, u16 height);
|
||||
void dispc_set_channel_out(enum omap_plane plane,
|
||||
enum omap_channel channel_out);
|
||||
|
||||
int dispc_setup_plane(enum omap_plane plane,
|
||||
u32 paddr, u16 screen_width,
|
||||
u16 pos_x, u16 pos_y,
|
||||
u16 width, u16 height,
|
||||
u16 out_width, u16 out_height,
|
||||
enum omap_color_mode color_mode,
|
||||
bool ilace,
|
||||
enum omap_dss_rotation_type rotation_type,
|
||||
u8 rotation, bool mirror,
|
||||
u8 global_alpha);
|
||||
|
||||
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);
|
||||
int dispc_enable_plane(enum omap_plane plane, bool enable);
|
||||
void dispc_enable_replication(enum omap_plane plane, bool enable);
|
||||
|
||||
void dispc_set_parallel_interface_mode(enum omap_parallel_interface_mode mode);
|
||||
void dispc_set_tft_data_lines(u8 data_lines);
|
||||
void dispc_set_lcd_display_type(enum omap_lcd_display_type type);
|
||||
void dispc_set_loadmode(enum omap_dss_load_mode mode);
|
||||
|
||||
void dispc_set_default_color(enum omap_channel channel, u32 color);
|
||||
u32 dispc_get_default_color(enum omap_channel channel);
|
||||
void dispc_set_trans_key(enum omap_channel ch,
|
||||
enum omap_dss_trans_key_type type,
|
||||
u32 trans_key);
|
||||
void dispc_get_trans_key(enum omap_channel ch,
|
||||
enum omap_dss_trans_key_type *type,
|
||||
u32 *trans_key);
|
||||
void dispc_enable_trans_key(enum omap_channel ch, bool enable);
|
||||
void dispc_enable_alpha_blending(enum omap_channel ch, bool enable);
|
||||
bool dispc_trans_key_enabled(enum omap_channel ch);
|
||||
bool dispc_alpha_blending_enabled(enum omap_channel ch);
|
||||
|
||||
bool dispc_lcd_timings_ok(struct omap_video_timings *timings);
|
||||
void dispc_set_lcd_timings(struct omap_video_timings *timings);
|
||||
unsigned long dispc_fclk_rate(void);
|
||||
unsigned long dispc_lclk_rate(void);
|
||||
unsigned long dispc_pclk_rate(void);
|
||||
void dispc_set_pol_freq(enum omap_panel_config config, u8 acbi, u8 acb);
|
||||
void dispc_find_clk_divs(bool is_tft, unsigned long req_pck, unsigned long fck,
|
||||
struct dispc_clock_info *cinfo);
|
||||
int dispc_calc_clock_rates(unsigned long dispc_fclk_rate,
|
||||
struct dispc_clock_info *cinfo);
|
||||
int dispc_set_clock_div(struct dispc_clock_info *cinfo);
|
||||
int dispc_get_clock_div(struct dispc_clock_info *cinfo);
|
||||
|
||||
|
||||
/* VENC */
|
||||
int venc_init(struct platform_device *pdev);
|
||||
void venc_exit(void);
|
||||
void venc_dump_regs(struct seq_file *s);
|
||||
int venc_init_display(struct omap_dss_device *display);
|
||||
|
||||
/* RFBI */
|
||||
int rfbi_init(void);
|
||||
void rfbi_exit(void);
|
||||
void rfbi_dump_regs(struct seq_file *s);
|
||||
|
||||
int rfbi_configure(int rfbi_module, int bpp, int lines);
|
||||
void rfbi_enable_rfbi(bool enable);
|
||||
void rfbi_transfer_area(u16 width, u16 height,
|
||||
void (callback)(void *data), void *data);
|
||||
void rfbi_set_timings(int rfbi_module, struct rfbi_timings *t);
|
||||
unsigned long rfbi_get_max_tx_rate(void);
|
||||
int rfbi_init_display(struct omap_dss_device *display);
|
||||
|
||||
#endif
|
Loading…
Reference in New Issue
Block a user