mirror of
				https://github.com/AetherDroid/android_kernel_samsung_on5xelte.git
				synced 2025-10-31 16:18:51 +01:00 
			
		
		
		
	Fixed MTP to work with TWRP
This commit is contained in:
		
						commit
						f6dfaef42e
					
				
					 50820 changed files with 20846062 additions and 0 deletions
				
			
		
							
								
								
									
										60
									
								
								drivers/video/fbdev/exynos/decon_8890/Kconfig
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										60
									
								
								drivers/video/fbdev/exynos/decon_8890/Kconfig
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,60 @@ | |||
| config EXYNOS_DECON_8890 | ||||
| 	bool "Samsung Exynos8890 Display system (VPP, DECON, MIPI, HDMI)" | ||||
| 	depends on FB | ||||
| 
 | ||||
| if EXYNOS_DECON_8890 | ||||
| config USE_VSYNC_SKIP | ||||
| 	bool "Vsync Skip Enable" | ||||
| 	depends on EXYNOS_DECON_8890 | ||||
| 	default n | ||||
| 	help | ||||
| 	  Say Y here if you want to enable vsync skip feature for DFS solution. | ||||
| 
 | ||||
| config EXYNOS_DECON_FB | ||||
| 	bool "Samsung DECON Framebuffer driver" | ||||
| 	depends on EXYNOS_DECON_8890 | ||||
| 	select MEDIA_EXYNOS | ||||
| 	default y | ||||
| 	help | ||||
| 	  Say Y here if you want support for the DECON in Samsung S5P SoCs. | ||||
| 	  This device produce image data to one of output interfaces. | ||||
| 
 | ||||
| config EXYNOS_MIPI_DSI | ||||
| 	bool "Samsung Exynos MIPI-DSI driver" | ||||
| 	depends on EXYNOS_DECON_8890 | ||||
| 	default y | ||||
| 	help | ||||
| 	  Enable MIPI-DSI driver. | ||||
| 
 | ||||
| config DECON_MIPI_DSI_PKTGO | ||||
| 	bool "Samsung Exynos MIPI-DSI Packet Go" | ||||
| 	depends on EXYNOS_MIPI_DSI | ||||
| 	default n | ||||
| 	help | ||||
| 	  Enable/disable MIPI-DSI Packet Go function | ||||
| 
 | ||||
| config DECON_LPD_DISPLAY | ||||
|         bool "Decon Low Power Display MODE" | ||||
|         depends on EXYNOS_DECON_8890 | ||||
|         default n | ||||
| 
 | ||||
| config FB_WINDOW_UPDATE | ||||
|         bool "DECON window update mode" | ||||
|         depends on EXYNOS_DECON_8890 | ||||
|         default n | ||||
| 
 | ||||
| config DECON_BLOCKING_MODE | ||||
| 	bool "DECON blocking mode" | ||||
|         depends on EXYNOS_DECON_8890 | ||||
|         default n | ||||
| 
 | ||||
| config DECON_EVENT_LOG | ||||
| 	bool "Display sub-system event logger (DECON/DSIM/VPP)" | ||||
|         depends on DEBUG_INFO && EXYNOS_DECON_8890 | ||||
|         default y | ||||
| 
 | ||||
| source "drivers/video/fbdev/exynos/decon_8890/vpp/Kconfig" | ||||
| 
 | ||||
| endif | ||||
| 
 | ||||
| source "drivers/video/fbdev/exynos/decon_8890/panels/Kconfig" | ||||
							
								
								
									
										14
									
								
								drivers/video/fbdev/exynos/decon_8890/Makefile
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										14
									
								
								drivers/video/fbdev/exynos/decon_8890/Makefile
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,14 @@ | |||
| #
 | ||||
| # Copyright (c) 2013 Samsung Electronics Co., Ltd.
 | ||||
| #		http://www.samsung.com
 | ||||
| #
 | ||||
| # Licensed under GPLv2
 | ||||
| #
 | ||||
| 
 | ||||
| obj-$(CONFIG_EXYNOS_VPP) += vpp/ | ||||
| obj-$(CONFIG_EXYNOS_MIPI_DSI) += dsim.o | ||||
| dsim-y += dsim_drv.o dsim_reg_8890.o | ||||
| obj-$(CONFIG_EXYNOS_DECON_8890) += decon.o | ||||
| decon-y += decon_core.o decon_f.o decon_s.o decon_t.o decon_dsi.o decon_helper.o decon_bts.o | ||||
| obj-$(CONFIG_SOC_EXYNOS8890) += decon_reg_8890.o | ||||
| obj-y += panels/ | ||||
							
								
								
									
										857
									
								
								drivers/video/fbdev/exynos/decon_8890/decon.h
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										857
									
								
								drivers/video/fbdev/exynos/decon_8890/decon.h
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,857 @@ | |||
| /*
 | ||||
|  * Copyright (c) 2014 Samsung Electronics Co., Ltd. | ||||
|  *		http://www.samsung.com
 | ||||
|  * | ||||
|  * Header file for Exynos DECON driver | ||||
|  * | ||||
|  * 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. | ||||
| */ | ||||
| 
 | ||||
| #ifndef ___SAMSUNG_DECON_H__ | ||||
| #define ___SAMSUNG_DECON_H__ | ||||
| 
 | ||||
| #include <linux/fb.h> | ||||
| #include <linux/kernel.h> | ||||
| #include <linux/spinlock.h> | ||||
| #include <linux/interrupt.h> | ||||
| #include <linux/wait.h> | ||||
| #include <linux/kthread.h> | ||||
| #include <linux/pm_qos.h> | ||||
| #include <linux/delay.h> | ||||
| #include <linux/seq_file.h> | ||||
| #include <media/v4l2-device.h> | ||||
| #include <media/videobuf2-core.h> | ||||
| #include <media/exynos_mc.h> | ||||
| 
 | ||||
| #include "regs-decon.h" | ||||
| #include "decon_common.h" | ||||
| #include "./panels/decon_lcd.h" | ||||
| 
 | ||||
| extern struct ion_device *ion_exynos; | ||||
| extern struct decon_device *decon_f_drvdata; | ||||
| extern struct decon_device *decon_s_drvdata; | ||||
| extern struct decon_device *decon_t_drvdata; | ||||
| extern int decon_log_level; | ||||
| 
 | ||||
| #define NUM_DECON_IPS		(3) | ||||
| #define DRIVER_NAME		"decon" | ||||
| #define MAX_NAME_SIZE		32 | ||||
| 
 | ||||
| #define MAX_DECON_PADS		9 | ||||
| #define DECON_PAD_WB		8 | ||||
| 
 | ||||
| #define MAX_BUF_PLANE_CNT	3 | ||||
| #define DECON_ENTER_LPD_CNT	3 | ||||
| #define MIN_BLK_MODE_WIDTH	144 | ||||
| #define MIN_BLK_MODE_HEIGHT	10 | ||||
| 
 | ||||
| #define VSYNC_TIMEOUT_MSEC	200 | ||||
| #define MAX_BW_PER_WINDOW	(2560 * 1600 * 4 * 60) | ||||
| #define LCD_DEFAULT_BPP		24 | ||||
| 
 | ||||
| #define DECON_TZPC_OFFSET	3 | ||||
| #define MAX_DMA_TYPE		10 | ||||
| #define MAX_FRM_DONE_WAIT	34 | ||||
| 
 | ||||
| #define DISP_UTIL		70 | ||||
| #define DECON_INT_UTIL		65 | ||||
| #ifndef NO_CNT_TH | ||||
| /* BTS driver defines the Threshold */ | ||||
| #define	NO_CNT_TH		10 | ||||
| #endif | ||||
| 
 | ||||
| #define UNDERRUN_FILTER_INTERVAL_MS    100 | ||||
| #define UNDERRUN_FILTER_INIT           0 | ||||
| #define UNDERRUN_FILTER_IDLE           1 | ||||
| #define DECON_UNDERRUN_THRESHOLD	0 | ||||
| #ifdef CONFIG_FB_WINDOW_UPDATE | ||||
| #define DECON_WIN_UPDATE_IDX	(8) | ||||
| #define decon_win_update_dbg(fmt, ...)					\ | ||||
| 	do {								\ | ||||
| 		if (decon_log_level >= 7)				\ | ||||
| 			pr_info(pr_fmt(fmt), ##__VA_ARGS__);		\ | ||||
| 	} while (0) | ||||
| #else | ||||
| #define decon_win_update_dbg(fmt, ...) while (0) | ||||
| #endif | ||||
| 
 | ||||
| #ifndef KHZ | ||||
| #define KHZ (1000) | ||||
| #endif | ||||
| 
 | ||||
| #ifndef MHZ | ||||
| #define MHZ (1000*1000) | ||||
| #endif | ||||
| 
 | ||||
| #define decon_err(fmt, ...)							\ | ||||
| 	do {									\ | ||||
| 		if (decon_log_level >= 3) {					\ | ||||
| 			pr_err(pr_fmt(fmt), ##__VA_ARGS__);			\ | ||||
| 			exynos_ss_printk(fmt, ##__VA_ARGS__);			\ | ||||
| 		}								\ | ||||
| 	} while (0) | ||||
| 
 | ||||
| #define decon_warn(fmt, ...)							\ | ||||
| 	do {									\ | ||||
| 		if (decon_log_level >= 4) {					\ | ||||
| 			pr_warn(pr_fmt(fmt), ##__VA_ARGS__);			\ | ||||
| 			exynos_ss_printk(fmt, ##__VA_ARGS__);			\ | ||||
| 		}								\ | ||||
| 	} while (0) | ||||
| 
 | ||||
| #define decon_info(fmt, ...)							\ | ||||
| 	do {									\ | ||||
| 		if (decon_log_level >= 6)					\ | ||||
| 			pr_info(pr_fmt(fmt), ##__VA_ARGS__);			\ | ||||
| 	} while (0) | ||||
| 
 | ||||
| #define decon_dbg(fmt, ...)							\ | ||||
| 	do {									\ | ||||
| 		if (decon_log_level >= 7)					\ | ||||
| 			pr_info(pr_fmt(fmt), ##__VA_ARGS__);			\ | ||||
| 	} while (0) | ||||
| 
 | ||||
| /*
 | ||||
|  * DECON_STATE_ON : disp power on, decon/dsim clock on & lcd on | ||||
|  * DECON_STATE_LPD_ENT_REQ : disp power on, decon/dsim clock on, lcd on & request for LPD | ||||
|  * DECON_STATE_LPD_EXIT_REQ : disp power off, decon/dsim clock off, lcd on & request for LPD exit. | ||||
|  * DECON_STATE_LPD : disp power off, decon/dsim clock off & lcd on | ||||
|  * DECON_STATE_OFF : disp power off, decon/dsim clock off & lcd off | ||||
|  */ | ||||
| enum decon_state { | ||||
| 	DECON_STATE_INIT = 0, | ||||
| 	DECON_STATE_ON, | ||||
| 	DECON_STATE_LPD_ENT_REQ, | ||||
| 	DECON_STATE_LPD_EXIT_REQ, | ||||
| 	DECON_STATE_LPD, | ||||
| 	DECON_STATE_OFF | ||||
| }; | ||||
| 
 | ||||
| struct exynos_decon_platdata { | ||||
| 	enum decon_psr_mode	psr_mode; | ||||
| 	enum decon_trig_mode	trig_mode; | ||||
| 	enum decon_dsi_mode	dsi_mode; | ||||
| 	enum decon_output_type	out_type; | ||||
| 	int	max_win; | ||||
| 	int	default_win; | ||||
| }; | ||||
| 
 | ||||
| struct decon_vsync { | ||||
| 	wait_queue_head_t	wait; | ||||
| 	ktime_t			timestamp; | ||||
| 	bool			active; | ||||
| 	int			irq_refcount; | ||||
| 	struct mutex		irq_lock; | ||||
| 	struct task_struct	*thread; | ||||
| }; | ||||
| 
 | ||||
| /*
 | ||||
|  * @width: The width of display in mm | ||||
|  * @height: The height of display in mm | ||||
|  */ | ||||
| struct decon_fb_videomode { | ||||
| 	struct fb_videomode videomode; | ||||
| 	unsigned short width; | ||||
| 	unsigned short height; | ||||
| 
 | ||||
| 	u8 cs_setup_time; | ||||
| 	u8 wr_setup_time; | ||||
| 	u8 wr_act_time; | ||||
| 	u8 wr_hold_time; | ||||
| 	u8 auto_cmd_rate; | ||||
| 	u8 frame_skip:2; | ||||
| 	u8 rs_pol:1; | ||||
| }; | ||||
| 
 | ||||
| struct decon_fb_pd_win { | ||||
| 	struct decon_fb_videomode win_mode; | ||||
| 
 | ||||
| 	unsigned short		default_bpp; | ||||
| 	unsigned short		max_bpp; | ||||
| 	unsigned short		virtual_x; | ||||
| 	unsigned short		virtual_y; | ||||
| 	unsigned short		width; | ||||
| 	unsigned short		height; | ||||
| }; | ||||
| 
 | ||||
| struct decon_dma_buf_data { | ||||
| 	struct ion_handle		*ion_handle; | ||||
| 	struct dma_buf			*dma_buf; | ||||
| 	struct dma_buf_attachment	*attachment; | ||||
| 	struct sg_table			*sg_table; | ||||
| 	dma_addr_t			dma_addr; | ||||
| 	struct sync_fence		*fence; | ||||
| }; | ||||
| 
 | ||||
| struct decon_win_rect { | ||||
| 	int x; | ||||
| 	int y; | ||||
| 	u32 w; | ||||
| 	u32 h; | ||||
| }; | ||||
| 
 | ||||
| struct decon_resources { | ||||
| 	struct clk *dpll; | ||||
| 	struct clk *pclk; | ||||
| 	struct clk *eclk; | ||||
| 	struct clk *eclk_leaf; | ||||
| 	struct clk *vclk; | ||||
| 	struct clk *vclk_leaf; | ||||
| }; | ||||
| 
 | ||||
| struct decon_rect { | ||||
| 	int	left; | ||||
| 	int	top; | ||||
| 	int	right; | ||||
| 	int	bottom; | ||||
| }; | ||||
| 
 | ||||
| struct decon_win { | ||||
| 	struct decon_fb_pd_win		windata; | ||||
| 	struct decon_device		*decon; | ||||
| 	struct fb_info			*fbinfo; | ||||
| 	struct media_pad		pad; | ||||
| 
 | ||||
| 	struct decon_fb_videomode	win_mode; | ||||
| 	struct decon_dma_buf_data	dma_buf_data[MAX_BUF_PLANE_CNT]; | ||||
| 	int				plane_cnt; | ||||
| 	struct fb_var_screeninfo	prev_var; | ||||
| 	struct fb_fix_screeninfo	prev_fix; | ||||
| 
 | ||||
| 	int	fps; | ||||
| 	int	index; | ||||
| 	int	use; | ||||
| 	int	local; | ||||
| 	unsigned long	state; | ||||
| 	int	vpp_id; | ||||
| 	u32	pseudo_palette[16]; | ||||
| }; | ||||
| 
 | ||||
| struct decon_user_window { | ||||
| 	int x; | ||||
| 	int y; | ||||
| }; | ||||
| 
 | ||||
| struct s3c_fb_user_plane_alpha { | ||||
| 	int		channel; | ||||
| 	unsigned char	red; | ||||
| 	unsigned char	green; | ||||
| 	unsigned char	blue; | ||||
| }; | ||||
| 
 | ||||
| struct s3c_fb_user_chroma { | ||||
| 	int		enabled; | ||||
| 	unsigned char	red; | ||||
| 	unsigned char	green; | ||||
| 	unsigned char	blue; | ||||
| }; | ||||
| 
 | ||||
| struct s3c_fb_user_ion_client { | ||||
| 	int	fd[MAX_BUF_PLANE_CNT]; | ||||
| 	int	offset; | ||||
| }; | ||||
| 
 | ||||
| enum decon_pixel_format { | ||||
| 	/* RGB 32bit */ | ||||
| 	DECON_PIXEL_FORMAT_ARGB_8888 = 0, | ||||
| 	DECON_PIXEL_FORMAT_ABGR_8888, | ||||
| 	DECON_PIXEL_FORMAT_RGBA_8888, | ||||
| 	DECON_PIXEL_FORMAT_BGRA_8888, | ||||
| 	DECON_PIXEL_FORMAT_XRGB_8888, | ||||
| 	DECON_PIXEL_FORMAT_XBGR_8888, | ||||
| 	DECON_PIXEL_FORMAT_RGBX_8888, | ||||
| 	DECON_PIXEL_FORMAT_BGRX_8888, | ||||
| 	/* RGB 16 bit */ | ||||
| 	DECON_PIXEL_FORMAT_RGBA_5551, | ||||
| 	DECON_PIXEL_FORMAT_RGB_565, | ||||
| 	/* YUV422 2P */ | ||||
| 	DECON_PIXEL_FORMAT_NV16, | ||||
| 	DECON_PIXEL_FORMAT_NV61, | ||||
| 	/* YUV422 3P */ | ||||
| 	DECON_PIXEL_FORMAT_YVU422_3P, | ||||
| 	/* YUV420 2P */ | ||||
| 	DECON_PIXEL_FORMAT_NV12, | ||||
| 	DECON_PIXEL_FORMAT_NV21, | ||||
| 	DECON_PIXEL_FORMAT_NV12M, | ||||
| 	DECON_PIXEL_FORMAT_NV21M, | ||||
| 	/* YUV420 3P */ | ||||
| 	DECON_PIXEL_FORMAT_YUV420, | ||||
| 	DECON_PIXEL_FORMAT_YVU420, | ||||
| 	DECON_PIXEL_FORMAT_YUV420M, | ||||
| 	DECON_PIXEL_FORMAT_YVU420M, | ||||
| 
 | ||||
| 	DECON_PIXEL_FORMAT_MAX, | ||||
| }; | ||||
| 
 | ||||
| enum decon_blending { | ||||
| 	DECON_BLENDING_NONE = 0, | ||||
| 	DECON_BLENDING_PREMULT = 1, | ||||
| 	DECON_BLENDING_COVERAGE = 2, | ||||
| 	DECON_BLENDING_MAX = 3, | ||||
| }; | ||||
| 
 | ||||
| enum vpp_rotate { | ||||
| 	VPP_ROT_NORMAL = 0x0, | ||||
| 	VPP_ROT_XFLIP, | ||||
| 	VPP_ROT_YFLIP, | ||||
| 	VPP_ROT_180, | ||||
| 	VPP_ROT_90, | ||||
| 	VPP_ROT_90_XFLIP, | ||||
| 	VPP_ROT_90_YFLIP, | ||||
| 	VPP_ROT_270, | ||||
| }; | ||||
| 
 | ||||
| enum vpp_csc_eq { | ||||
| 	BT_601_NARROW = 0x0, | ||||
| 	BT_601_WIDE, | ||||
| 	BT_709_NARROW, | ||||
| 	BT_709_WIDE, | ||||
| }; | ||||
| 
 | ||||
| enum vpp_stop_status { | ||||
| 	VPP_STOP_NORMAL = 0x0, | ||||
| 	VPP_STOP_LPD, | ||||
| 	VPP_STOP_ERR, | ||||
| }; | ||||
| 
 | ||||
| struct vpp_params { | ||||
| 	dma_addr_t addr[MAX_BUF_PLANE_CNT]; | ||||
| 	enum vpp_rotate rot; | ||||
| 	enum vpp_csc_eq eq_mode; | ||||
| }; | ||||
| 
 | ||||
| struct decon_frame { | ||||
| 	int x; | ||||
| 	int y; | ||||
| 	u32 w; | ||||
| 	u32 h; | ||||
| 	u32 f_w; | ||||
| 	u32 f_h; | ||||
| }; | ||||
| 
 | ||||
| struct decon_win_config { | ||||
| 	enum { | ||||
| 		DECON_WIN_STATE_DISABLED = 0, | ||||
| 		DECON_WIN_STATE_COLOR, | ||||
| 		DECON_WIN_STATE_BUFFER, | ||||
| 		DECON_WIN_STATE_UPDATE, | ||||
| 	} state; | ||||
| 
 | ||||
| 	/* Reusability:This struct is used for IDMA and ODMA */ | ||||
| 	union { | ||||
| 		__u32 color; | ||||
| 		struct { | ||||
| 			int				fd_idma[3]; | ||||
| 			int				fence_fd; | ||||
| 			int				plane_alpha; | ||||
| 			enum decon_blending		blending; | ||||
| 			enum decon_idma_type		idma_type; | ||||
| 			enum decon_pixel_format		format; | ||||
| 			struct vpp_params		vpp_parm; | ||||
| 			/* no read area of IDMA */ | ||||
| 			struct decon_win_rect		block_area; | ||||
| 			struct decon_win_rect		transparent_area; | ||||
| 			struct decon_win_rect		opaque_area; | ||||
| 			/* source framebuffer coordinates */ | ||||
| 			struct decon_frame		src; | ||||
| 		}; | ||||
| 	}; | ||||
| 
 | ||||
| 	/* destination OSD coordinates */ | ||||
| 	struct decon_frame dst; | ||||
| 	bool protection; | ||||
| }; | ||||
| 
 | ||||
| struct decon_reg_data { | ||||
| 	struct list_head		list; | ||||
| 	struct decon_window_regs	win_regs[MAX_DECON_WIN]; | ||||
| 	struct decon_dma_buf_data	dma_buf_data[MAX_DECON_WIN + 1][MAX_BUF_PLANE_CNT]; | ||||
| 	unsigned int			bandwidth; | ||||
| 	unsigned int			num_of_window; | ||||
| 	u32				win_overlap_cnt; | ||||
| 	u32				bw; | ||||
| 	u32				disp_bw; | ||||
| 	u32                             int_bw; | ||||
| 	struct decon_rect		overlap_rect; | ||||
| 	struct decon_win_config		vpp_config[MAX_DECON_WIN + 1]; | ||||
| 	struct decon_win_rect		block_rect[MAX_DECON_WIN]; | ||||
| #ifdef CONFIG_FB_WINDOW_UPDATE | ||||
| 	struct decon_win_rect		update_win; | ||||
| 	bool				need_update; | ||||
| #endif | ||||
| 	bool				protection[MAX_DECON_WIN]; | ||||
| }; | ||||
| 
 | ||||
| struct decon_win_config_data { | ||||
| 	int	fence; | ||||
| 	int	fd_odma; | ||||
| 	struct decon_win_config config[MAX_DECON_WIN + 1]; | ||||
| }; | ||||
| 
 | ||||
| union decon_ioctl_data { | ||||
| 	struct decon_user_window user_window; | ||||
| 	struct s3c_fb_user_plane_alpha user_alpha; | ||||
| 	struct s3c_fb_user_chroma user_chroma; | ||||
| 	struct decon_win_config_data win_data; | ||||
| 	u32 vsync; | ||||
| }; | ||||
| 
 | ||||
| struct decon_underrun_stat { | ||||
| 	int	prev_bw; | ||||
| 	int	prev_int_bw; | ||||
| 	int	prev_disp_bw; | ||||
| 	int	chmap; | ||||
| 	int	fifo_level; | ||||
| 	int	underrun_cnt; | ||||
| 	unsigned long aclk; | ||||
| 	unsigned long lh_disp0; | ||||
| 	unsigned long mif_pll; | ||||
| 	unsigned long used_windows; | ||||
| }; | ||||
| 
 | ||||
| struct disp_ss_size_info { | ||||
| 	u32 w_in; | ||||
| 	u32 h_in; | ||||
| 	u32 w_out; | ||||
| 	u32 h_out; | ||||
| }; | ||||
| 
 | ||||
| #ifdef CONFIG_DECON_EVENT_LOG | ||||
| /**
 | ||||
|  * Display Subsystem event management status. | ||||
|  * | ||||
|  * These status labels are used internally by the DECON to indicate the | ||||
|  * current status of a device with operations. | ||||
|  */ | ||||
| typedef enum disp_ss_event_type { | ||||
| 	/* Related with FB interface */ | ||||
| 	DISP_EVT_BLANK = 0, | ||||
| 	DISP_EVT_UNBLANK, | ||||
| 	DISP_EVT_ACT_VSYNC, | ||||
| 	DISP_EVT_DEACT_VSYNC, | ||||
| 	DISP_EVT_WIN_CONFIG, | ||||
| 
 | ||||
| 	/* Related with interrupt */ | ||||
| 	DISP_EVT_TE_INTERRUPT, | ||||
| 	DISP_EVT_UNDERRUN, | ||||
| 	DISP_EVT_DECON_FRAMEDONE, | ||||
| 	DISP_EVT_DSIM_FRAMEDONE, | ||||
| 	DISP_EVT_RSC_CONFLICT, | ||||
| 
 | ||||
| 	/* Related with async event */ | ||||
| 	DISP_EVT_UPDATE_HANDLER, | ||||
| 	DISP_EVT_DSIM_COMMAND, | ||||
| 	DISP_EVT_TRIG_MASK, | ||||
| 	DISP_EVT_TRIG_UNMASK, | ||||
| 	DISP_EVT_DECON_FRAMEDONE_WAIT, | ||||
| 	DISP_EVT_DECON_SHUTDOWN, | ||||
| 	DISP_EVT_DSIM_SHUTDOWN, | ||||
| 
 | ||||
| 	/* Related with VPP */ | ||||
| 	DISP_EVT_VPP_WINCON, | ||||
| 	DISP_EVT_VPP_FRAMEDONE, | ||||
| 	DISP_EVT_VPP_STOP, | ||||
| 	DISP_EVT_VPP_UPDATE_DONE, | ||||
| 	DISP_EVT_VPP_SHADOW_UPDATE, | ||||
| 	DISP_EVT_VPP_SUSPEND, | ||||
| 	DISP_EVT_VPP_RESUME, | ||||
| 
 | ||||
| 	/* Related with PM */ | ||||
| 	DISP_EVT_DECON_SUSPEND, | ||||
| 	DISP_EVT_DECON_RESUME, | ||||
| 	DISP_EVT_ENTER_LPD, | ||||
| 	DISP_EVT_EXIT_LPD, | ||||
| 	DISP_EVT_DSIM_SUSPEND, | ||||
| 	DISP_EVT_DSIM_RESUME, | ||||
| 	DISP_EVT_ENTER_ULPS, | ||||
| 	DISP_EVT_EXIT_ULPS, | ||||
| 
 | ||||
| 	DISP_EVT_LINECNT_ZERO, | ||||
| 
 | ||||
| 	/* write-back events */ | ||||
| 	DISP_EVT_WB_SET_BUFFER, | ||||
| 	DISP_EVT_WB_SW_TRIGGER, | ||||
| 
 | ||||
| 	DISP_EVT_MAX, /* End of EVENT */ | ||||
| } disp_ss_event_t; | ||||
| 
 | ||||
| /* Related with PM */ | ||||
| struct disp_log_pm { | ||||
| 	u32 pm_status;		/* ACTIVE(1) or SUSPENDED(0) */ | ||||
| 	ktime_t elapsed;	/* End time - Start time */ | ||||
| }; | ||||
| 
 | ||||
| /* Related with S3CFB_WIN_CONFIG */ | ||||
| struct decon_update_reg_data { | ||||
| 	struct decon_window_regs 	win_regs[MAX_DECON_WIN]; | ||||
| 	struct decon_win_config 	win_config[MAX_DECON_WIN + 1]; | ||||
| 	struct decon_win_rect 		win; | ||||
| }; | ||||
| 
 | ||||
| /* Related with MIPI COMMAND read/write */ | ||||
| #define DISP_CALLSTACK_MAX 4 | ||||
| struct dsim_log_cmd_buf { | ||||
| 	u32 id; | ||||
| 	u8 buf; | ||||
| 	void *caller[DISP_CALLSTACK_MAX]; | ||||
| }; | ||||
| 
 | ||||
| /* Related with VPP */ | ||||
| struct disp_log_vpp { | ||||
| 	u32 id; | ||||
| 	u32 start_cnt; | ||||
| 	u32 done_cnt; | ||||
| }; | ||||
| 
 | ||||
| /**
 | ||||
|  * struct disp_ss_log - Display Subsystem Log | ||||
|  * This struct includes DECON/DSIM/VPP | ||||
|  */ | ||||
| struct disp_ss_log { | ||||
| 	ktime_t time; | ||||
| 	disp_ss_event_t type; | ||||
| 	union { | ||||
| 		struct disp_log_vpp vpp; | ||||
| 		struct decon_update_reg_data reg; | ||||
| 		struct dsim_log_cmd_buf cmd_buf; | ||||
| 		struct disp_log_pm pm; | ||||
| 	} data; | ||||
| }; | ||||
| 
 | ||||
| struct disp_ss_size_err_info { | ||||
| 	ktime_t time; | ||||
| 	struct disp_ss_size_info info; | ||||
| }; | ||||
| 
 | ||||
| /* Definitions below are used in the DECON */ | ||||
| #define	DISP_EVENT_LOG_MAX	SZ_2K | ||||
| #define	DISP_EVENT_PRINT_MAX	512 | ||||
| #define	DISP_EVENT_SIZE_ERR_MAX	16 | ||||
| typedef enum disp_ss_event_log_level_type { | ||||
| 	DISP_EVENT_LEVEL_LOW = 0, | ||||
| 	DISP_EVENT_LEVEL_HIGH, | ||||
| } disp_ss_log_level_t; | ||||
| 
 | ||||
| /* APIs below are used in the DECON/DSIM/VPP driver */ | ||||
| #define DISP_SS_EVENT_START() ktime_t start = ktime_get() | ||||
| void DISP_SS_EVENT_LOG(disp_ss_event_t type, struct v4l2_subdev *sd, ktime_t time); | ||||
| void DISP_SS_EVENT_LOG_WINCON(struct v4l2_subdev *sd, struct decon_reg_data *regs); | ||||
| void DISP_SS_EVENT_LOG_CMD(struct v4l2_subdev *sd, u32 cmd_id, unsigned long data); | ||||
| void DISP_SS_EVENT_SHOW(struct seq_file *s, struct decon_device *decon); | ||||
| void DISP_SS_EVENT_SIZE_ERR_LOG(struct v4l2_subdev *sd, struct disp_ss_size_info *info); | ||||
| #else /*!*/ | ||||
| #define DISP_SS_EVENT_START(...) do { } while(0) | ||||
| #define DISP_SS_EVENT_LOG(...) do { } while(0) | ||||
| #define DISP_SS_EVENT_LOG_WINCON(...) do { } while(0) | ||||
| #define DISP_SS_EVENT_LOG_CMD(...) do { } while(0) | ||||
| #define DISP_SS_EVENT_SHOW(...) do { } while(0) | ||||
| #define DISP_SS_EVENT_SIZE_ERR_LOG(...) do { } while(0) | ||||
| #endif | ||||
| 
 | ||||
| /**
 | ||||
| * END of CONFIG_DECON_EVENT_LOG | ||||
| */ | ||||
| 
 | ||||
| #define MAX_VPP_LOG	10 | ||||
| 
 | ||||
| struct vpp_drm_log { | ||||
| 	unsigned long long time; | ||||
| 	int decon_id; | ||||
| 	int line; | ||||
| 	bool protection; | ||||
| }; | ||||
| 
 | ||||
| /* VPP resource management */ | ||||
| enum decon_dma_state { | ||||
| 	DMA_IDLE = 0, | ||||
| 	DMA_RSVD, | ||||
| }; | ||||
| 
 | ||||
| struct dma_rsm { | ||||
| /* TODO: 1) BLK power & Clk management. 2) locking mechanism */ | ||||
| 	u32	dma_state[MAX_DMA_TYPE-1]; | ||||
| 	u32	decon_dma_map[MAX_DMA_TYPE-1]; | ||||
| }; | ||||
| 
 | ||||
| typedef struct decon_device decon_dev; | ||||
| struct decon_device { | ||||
| 	decon_dev			*decon[NUM_DECON_IPS]; | ||||
| 	struct dma_rsm			*dma_rsm; | ||||
| 	u32				default_idma; | ||||
| 	void __iomem			*regs; | ||||
| 	void __iomem			*ss_regs; | ||||
| 	void __iomem			*eint_pend; | ||||
| 	void __iomem			*eint_mask; | ||||
| 	struct device			*dev; | ||||
| 	struct exynos_decon_platdata	*pdata; | ||||
| 	struct media_pad		pads[MAX_DECON_PADS]; | ||||
| 	struct v4l2_subdev		sd; | ||||
| 	struct decon_win		*windows[MAX_DECON_WIN]; | ||||
| 	struct decon_resources		res; | ||||
| 	struct v4l2_subdev		*output_sd; | ||||
| 	struct exynos_md		*mdev; | ||||
| 
 | ||||
| 	struct mutex			update_regs_list_lock; | ||||
| 	struct list_head		update_regs_list; | ||||
| 	struct task_struct		*update_regs_thread; | ||||
| 	struct kthread_worker		update_regs_worker; | ||||
| 	struct kthread_work		update_regs_work; | ||||
| 	struct mutex			lpd_lock; | ||||
| 	struct work_struct		lpd_work; | ||||
| 	struct workqueue_struct		*lpd_wq; | ||||
| 	atomic_t			lpd_trig_cnt; | ||||
| 	atomic_t			lpd_block_cnt; | ||||
| 	bool				lpd_init_status; | ||||
| 
 | ||||
| 	struct ion_client		*ion_client; | ||||
| 	struct sw_sync_timeline		*timeline; | ||||
| 	int				timeline_max; | ||||
| 
 | ||||
| 	struct mutex			output_lock; | ||||
| 	struct mutex			mutex; | ||||
| 	spinlock_t			slock; | ||||
| 	struct decon_vsync		vsync_info; | ||||
| 	enum decon_state		state; | ||||
| 	enum decon_output_type		out_type; | ||||
| 	int				out_idx; | ||||
| 	u32				prev_bw; | ||||
| 	u32				prev_disp_bw; | ||||
| 	u32				prev_int_bw; | ||||
| 	u32				prev_frame_has_yuv; | ||||
| 	u32				cur_frame_has_yuv; | ||||
| 	int				default_bw; | ||||
| 	int				cur_overlap_cnt; | ||||
| 	int				id; | ||||
| 	int				n_sink_pad; | ||||
| 	int				n_src_pad; | ||||
| 	union decon_ioctl_data		ioctl_data; | ||||
| 	bool				vpp_used[MAX_VPP_SUBDEV]; | ||||
| 	bool				vpp_err_stat[MAX_VPP_SUBDEV]; | ||||
| 	u32				vpp_usage_bitmask; | ||||
| 	struct decon_lcd		*lcd_info; | ||||
| #ifdef CONFIG_FB_WINDOW_UPDATE | ||||
| 	struct decon_win_rect		update_win; | ||||
| 	bool				need_update; | ||||
| #endif | ||||
| 	struct decon_underrun_stat	underrun_stat; | ||||
| 	void __iomem			*cam_status[2]; | ||||
| 	u32				prev_protection_bitmask; | ||||
| 	u32				cur_protection_bitmask; | ||||
| 
 | ||||
| 	unsigned int			irq; | ||||
| 	struct dentry			*debug_root; | ||||
| #ifdef CONFIG_DECON_EVENT_LOG | ||||
| 	struct dentry			*debug_event; | ||||
| 	struct disp_ss_log		disp_ss_log[DISP_EVENT_LOG_MAX]; | ||||
| 	atomic_t			disp_ss_log_idx; | ||||
| 	disp_ss_log_level_t		disp_ss_log_level; | ||||
| 	u32				disp_ss_size_log_idx; | ||||
| 	struct disp_ss_size_err_info	disp_ss_size_log[DISP_EVENT_SIZE_ERR_MAX]; | ||||
| #endif | ||||
| 	struct pinctrl			*pinctrl; | ||||
|         struct pinctrl_state 		*decon_te_on; | ||||
|         struct pinctrl_state		*decon_te_off; | ||||
| 	struct pm_qos_request		mif_qos; | ||||
| 	struct pm_qos_request		int_qos; | ||||
| 	struct pm_qos_request		disp_qos; | ||||
| 	u32				disp_cur; | ||||
| 	u32				disp_prev; | ||||
| 	struct decon_init_bts		*bts_init_ops; | ||||
| 
 | ||||
| 	int				frame_done_cnt_cur; | ||||
| 	int				frame_done_cnt_target; | ||||
| 	int				frame_start_cnt_cur; | ||||
| 	int				frame_start_cnt_target; | ||||
| 	wait_queue_head_t		wait_frmdone; | ||||
| 	wait_queue_head_t		wait_vstatus; | ||||
| 	ktime_t				trig_mask_timestamp; | ||||
| 	int                             frame_idle; | ||||
| 	int				eint_status; | ||||
| 	struct work_struct		fifo_irq_work; | ||||
| 	struct workqueue_struct		*fifo_irq_wq; | ||||
| 	int				fifo_irq_status; | ||||
| 	struct vpp_drm_log vpp_log[MAX_VPP_LOG]; | ||||
| 	int log_cnt; | ||||
| 	int sw_te_wa; | ||||
| }; | ||||
| 
 | ||||
| static inline struct decon_device *get_decon_drvdata(u32 id) | ||||
| { | ||||
|         if (id == 0) | ||||
|                 return decon_f_drvdata; | ||||
|         else if (id == 1) | ||||
|                 return decon_s_drvdata; | ||||
| 	else | ||||
| 		return decon_t_drvdata; | ||||
| } | ||||
| 
 | ||||
| /* register access subroutines */ | ||||
| static inline u32 decon_read(u32 id, u32 reg_id) | ||||
| { | ||||
| 	struct decon_device *decon = get_decon_drvdata(id); | ||||
| 	return readl(decon->regs + reg_id); | ||||
| } | ||||
| 
 | ||||
| static inline u32 decon_read_mask(u32 id, u32 reg_id, u32 mask) | ||||
| { | ||||
| 	u32 val = decon_read(id, reg_id); | ||||
| 	val &= (mask); | ||||
| 	return val; | ||||
| } | ||||
| 
 | ||||
| static inline void decon_write(u32 id, u32 reg_id, u32 val) | ||||
| { | ||||
| 	struct decon_device *decon = get_decon_drvdata(id); | ||||
| 	writel(val, decon->regs + reg_id); | ||||
| } | ||||
| 
 | ||||
| static inline void decon_write_mask(u32 id, u32 reg_id, u32 val, u32 mask) | ||||
| { | ||||
| 	u32 old = decon_read(id, reg_id); | ||||
| 
 | ||||
| 	val = (val & mask) | (old & ~mask); | ||||
| 	decon_write(id, reg_id, val); | ||||
| } | ||||
| 
 | ||||
| /* common function API */ | ||||
| bool decon_validate_x_alignment(struct decon_device *decon, int x, u32 w, | ||||
| 		u32 bits_per_pixel); | ||||
| int create_link_mipi(struct decon_device *decon, int id); | ||||
| int decon_int_remap_eint(struct decon_device *decon); | ||||
| int decon_f_register_irq(struct platform_device *pdev, struct decon_device *decon); | ||||
| int decon_s_register_irq(struct platform_device *pdev, struct decon_device *decon); | ||||
| int decon_t_register_irq(struct platform_device *pdev, struct decon_device *decon); | ||||
| irqreturn_t decon_f_irq_handler(int irq, void *dev_data); | ||||
| irqreturn_t decon_s_irq_handler(int irq, void *dev_data); | ||||
| irqreturn_t decon_t_irq_handler(int irq, void *dev_data); | ||||
| int decon_f_get_clocks(struct decon_device *decon); | ||||
| int decon_s_get_clocks(struct decon_device *decon); | ||||
| int decon_t_get_clocks(struct decon_device *decon); | ||||
| void decon_f_set_clocks(struct decon_device *decon); | ||||
| void decon_s_set_clocks(struct decon_device *decon); | ||||
| void decon_t_set_clocks(struct decon_device *decon); | ||||
| int decon_t_set_lcd_info(struct decon_device *decon); | ||||
| int decon_register_lpd_work(struct decon_device *decon); | ||||
| int decon_exit_lpd(struct decon_device *decon); | ||||
| int decon_lpd_block_exit(struct decon_device *decon); | ||||
| int decon_lcd_off(struct decon_device *decon); | ||||
| int decon_enable(struct decon_device *decon); | ||||
| int decon_disable(struct decon_device *decon); | ||||
| int decon_tui_protection(struct decon_device *decon, bool tui_en); | ||||
| int decon_wait_for_vsync(struct decon_device *decon, u32 timeout); | ||||
| 
 | ||||
| /* internal only function API */ | ||||
| int decon_config_eint_for_te(struct platform_device *pdev, struct decon_device *decon); | ||||
| int decon_f_create_vsync_thread(struct decon_device *decon); | ||||
| int decon_f_create_psr_thread(struct decon_device *decon); | ||||
| void decon_f_destroy_vsync_thread(struct decon_device *decon); | ||||
| void decon_f_destroy_psr_thread(struct decon_device *decon); | ||||
| int decon_set_lcd_config(struct decon_device *decon); | ||||
| int decon_check_var(struct fb_var_screeninfo *var, struct fb_info *info); | ||||
| int decon_set_par(struct fb_info *info); | ||||
| int decon_pan_display(struct fb_var_screeninfo *var, struct fb_info *info); | ||||
| int decon_setcolreg(unsigned regno, | ||||
| 			    unsigned red, unsigned green, unsigned blue, | ||||
| 			    unsigned transp, struct fb_info *info); | ||||
| int decon_mmap(struct fb_info *info, struct vm_area_struct *vma); | ||||
| 
 | ||||
| /* POWER and ClOCK API */ | ||||
| int init_display_decon_clocks(struct device *dev); | ||||
| int disable_display_decon_clocks(struct device *dev); | ||||
| void decon_clock_on(struct decon_device *decon); | ||||
| void decon_clock_off(struct decon_device *decon); | ||||
| u32 decon_reg_get_cam_status(void __iomem *); | ||||
| void decon_reg_set_block_mode(u32 id, u32 win_idx, u32 x, u32 y, u32 h, u32 w, u32 enable); | ||||
| void decon_reg_set_tui_va(u32 id, u32 va); | ||||
| void decon_vpp_min_lock_release(struct decon_device *decon); | ||||
| u32 wincon(u32 transp_len, u32 a0, u32 a1, int plane_alpha, enum decon_blending blending); | ||||
| int find_subdev_mipi(struct decon_device *decon, int id); | ||||
| #define is_rotation(config) (config->vpp_parm.rot >= VPP_ROT_90) | ||||
| 
 | ||||
| /* LPD related */ | ||||
| static inline void decon_lpd_block(struct decon_device *decon) | ||||
| { | ||||
| 	if (decon) | ||||
| 		atomic_inc(&decon->lpd_block_cnt); | ||||
| } | ||||
| 
 | ||||
| static inline bool decon_is_lpd_blocked(struct decon_device *decon) | ||||
| { | ||||
| 	return (atomic_read(&decon->lpd_block_cnt) > 0); | ||||
| } | ||||
| 
 | ||||
| static inline int decon_get_lpd_block_cnt(struct decon_device *decon) | ||||
| { | ||||
| 	return (atomic_read(&decon->lpd_block_cnt)); | ||||
| } | ||||
| 
 | ||||
| static inline void decon_lpd_unblock(struct decon_device *decon) | ||||
| { | ||||
| 	if (decon) { | ||||
| 		if (decon_is_lpd_blocked(decon)) | ||||
| 			atomic_dec(&decon->lpd_block_cnt); | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| static inline void decon_lpd_block_reset(struct decon_device *decon) | ||||
| { | ||||
| 	if (decon) | ||||
| 		atomic_set(&decon->lpd_block_cnt, 0); | ||||
| } | ||||
| 
 | ||||
| static inline void decon_lpd_trig_reset(struct decon_device *decon) | ||||
| { | ||||
| 	if (decon) | ||||
| 		atomic_set(&decon->lpd_trig_cnt, 0); | ||||
| } | ||||
| 
 | ||||
| static inline bool is_cam_not_running(struct decon_device *decon) | ||||
| { | ||||
| 	if (!decon->id) | ||||
| 		return (!((decon_reg_get_cam_status(decon->cam_status[0]) & 0xF) || | ||||
| 		(decon_reg_get_cam_status(decon->cam_status[1]) & 0xF))); | ||||
| 	else | ||||
| 		return true; | ||||
| } | ||||
| static inline bool decon_lpd_enter_cond(struct decon_device *decon) | ||||
| { | ||||
| 	return ((atomic_read(&decon->lpd_block_cnt) <= 0) && is_cam_not_running(decon) | ||||
| 		&& (atomic_inc_return(&decon->lpd_trig_cnt) >= DECON_ENTER_LPD_CNT)); | ||||
| } | ||||
| 
 | ||||
| static inline bool decon_min_lock_cond(struct decon_device *decon) | ||||
| { | ||||
| 	return (atomic_read(&decon->lpd_block_cnt) <= 0); | ||||
| } | ||||
| 
 | ||||
| static inline u32 win_start_pos(int x, int y) | ||||
| { | ||||
| 	return (WIN_STRPTR_Y_F(y) | WIN_STRPTR_X_F(x)); | ||||
| } | ||||
| 
 | ||||
| static inline u32 win_end_pos(int x, int y,  u32 xres, u32 yres) | ||||
| { | ||||
| 	return (WIN_ENDPTR_Y_F(y + yres - 1) | WIN_ENDPTR_X_F(x + xres - 1)); | ||||
| } | ||||
| 
 | ||||
| /* IOCTL commands */ | ||||
| #define S3CFB_WIN_POSITION		_IOW('F', 203, \ | ||||
| 						struct decon_user_window) | ||||
| #define S3CFB_WIN_SET_PLANE_ALPHA	_IOW('F', 204, \ | ||||
| 						struct s3c_fb_user_plane_alpha) | ||||
| #define S3CFB_WIN_SET_CHROMA		_IOW('F', 205, \ | ||||
| 						struct s3c_fb_user_chroma) | ||||
| #define S3CFB_SET_VSYNC_INT		_IOW('F', 206, __u32) | ||||
| 
 | ||||
| #define S3CFB_GET_ION_USER_HANDLE	_IOWR('F', 208, \ | ||||
| 						struct s3c_fb_user_ion_client) | ||||
| #define S3CFB_WIN_CONFIG		_IOW('F', 209, \ | ||||
| 						struct decon_win_config_data) | ||||
| #define S3CFB_WIN_PSR_EXIT		_IOW('F', 210, int) | ||||
| 
 | ||||
| #define DECON_IOC_LPD_EXIT_LOCK		_IOW('L', 0, u32) | ||||
| #define DECON_IOC_LPD_UNLOCK		_IOW('L', 1, u32) | ||||
| 
 | ||||
| #endif /* ___SAMSUNG_DECON_H__ */ | ||||
							
								
								
									
										195
									
								
								drivers/video/fbdev/exynos/decon_8890/decon_bts.c
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										195
									
								
								drivers/video/fbdev/exynos/decon_8890/decon_bts.c
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,195 @@ | |||
|  /*
 | ||||
|  * Copyright (c) 2015 Samsung Electronics Co., Ltd. | ||||
|  *		http://www.samsung.com
 | ||||
|  * | ||||
|  * Core file for Samsung EXYNOS DECON driver | ||||
|  * | ||||
|  * 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. | ||||
|  */ | ||||
| 
 | ||||
| #include "decon_bts.h" | ||||
| #include "vpp/vpp.h" | ||||
| #include <soc/samsung/bts.h> | ||||
| 
 | ||||
| #define MULTI_FACTOR 		(1 << 10) | ||||
| #define VPP_MAX 		9 | ||||
| #define HALF_MIC 		2 | ||||
| #define PIX_PER_CLK 		2 | ||||
| #define ROTATION 		4 | ||||
| #define NOT_ROT 		1 | ||||
| #define RGB_FACTOR 		4 | ||||
| #define YUV_FACTOR 		4 | ||||
|  /* If use float factor, DATA format factor should be multiflied by 2
 | ||||
|  * And then, should be divided using FORMAT_FACTOR at the end of bw_eq | ||||
|  */ | ||||
| #define FORMAT_FACTOR 		2 | ||||
| #define DISP_FACTOR 		1 | ||||
| 
 | ||||
| #define ENUM_OFFSET 		2 | ||||
| 
 | ||||
| #ifdef CONFIG_PM_DEVFREQ | ||||
| void bts_int_mif_bw(struct vpp_dev *vpp) | ||||
| { | ||||
| 	struct decon_win_config *config = vpp->config; | ||||
| 	struct decon_frame *src = &config->src; | ||||
| 	struct decon_frame *dst = &config->dst; | ||||
| 	struct decon_device *decon = get_decon_drvdata(0); | ||||
| 	u32 vclk = (clk_get_rate(decon->res.vclk_leaf) * PIX_PER_CLK / MHZ); | ||||
| 	/* TODO, parse mic factor automatically at dt */ | ||||
| 	u32 mic_factor = HALF_MIC; /* 1/2 MIC */ | ||||
| 	u64 s_ratio_h, s_ratio_v = 0; | ||||
| 	/* bpl is multiplied 2, it should be divied at end of eq. */ | ||||
| 	u8 bpl = 0; | ||||
| 	u8 rot_factor = is_rotation(config) ? ROTATION : NOT_ROT; | ||||
| 	bool is_rotated = is_rotation(config) ? true : false; | ||||
| 
 | ||||
| 	if (is_rgb(config)) | ||||
| 		bpl = RGB_FACTOR; | ||||
| 	else if (is_yuv(config)) | ||||
| 		bpl = YUV_FACTOR; | ||||
| 	else | ||||
| 		bpl = RGB_FACTOR; | ||||
| 
 | ||||
| 	if (is_rotated) { | ||||
| 		s_ratio_h = MULTI_FACTOR * src->h / dst->w; | ||||
| 		s_ratio_v = MULTI_FACTOR * src->w / dst->h; | ||||
| 	} else { | ||||
| 		s_ratio_h = MULTI_FACTOR * src->w / dst->w; | ||||
| 		s_ratio_v = MULTI_FACTOR * src->h / dst->h; | ||||
| 	} | ||||
| 
 | ||||
| 	/* BW = (VCLK * MIC_factor * Data format * ScaleRatio_H * ScaleRatio_V * RotationFactor) */ | ||||
| 	vpp->cur_bw = vclk * mic_factor * bpl * s_ratio_h * s_ratio_v | ||||
| 		* rot_factor * KHZ / (MULTI_FACTOR * MULTI_FACTOR); | ||||
| } | ||||
| 
 | ||||
| void bts_disp_bw(struct vpp_dev *vpp) | ||||
| { | ||||
| 	struct decon_win_config *config = vpp->config; | ||||
| 	struct decon_frame *src = &config->src; | ||||
| 	struct decon_frame *dst = &config->dst; | ||||
| 	struct decon_device *decon = get_decon_drvdata(0); | ||||
| 	u32 vclk = (clk_get_rate(decon->res.vclk_leaf) * PIX_PER_CLK / MHZ); | ||||
| 	/* TODO, parse mic factor automatically at dt */ | ||||
| 	u32 mic_factor = HALF_MIC; /* 1/2 MIC */ | ||||
| 	/* TODO, parse lcd width automatically at dt */ | ||||
| 	u32 lcd_width = 1440; | ||||
| 	u64 s_ratio_h, s_ratio_v = 0; | ||||
| 
 | ||||
| 	u32 src_w = is_rotation(config) ? src->h : src->w; | ||||
| 	u32 src_h = is_rotation(config) ? src->w : src->h; | ||||
| 
 | ||||
| 	/* ACLK_DISP_400 [MHz] = (VCLK * MIC_factor * ScaleRatio_H * ScaleRatio_V * disp_factor) / 2 * (DST_width / LCD_width) */ | ||||
| 	s_ratio_h = (src_w <= dst->w) ? MULTI_FACTOR : MULTI_FACTOR * src_w / dst->w; | ||||
| 	s_ratio_v = (src_h <= dst->h) ? MULTI_FACTOR : MULTI_FACTOR * src_h / dst->h; | ||||
| 
 | ||||
| 	vpp->disp_cur_bw = vclk * mic_factor * s_ratio_h * s_ratio_v | ||||
| 		* DISP_FACTOR * KHZ * (MULTI_FACTOR * dst->w / lcd_width) | ||||
| 		/ (MULTI_FACTOR * MULTI_FACTOR * MULTI_FACTOR) / 2; | ||||
| } | ||||
| 
 | ||||
| void bts_mif_lock(struct vpp_dev *vpp) | ||||
| { | ||||
| 	struct decon_win_config *config = vpp->config; | ||||
| 
 | ||||
| 	if (is_rotation(config)) { | ||||
| 		pm_qos_update_request(&vpp->vpp_mif_qos, 1144000); | ||||
| 	} else { | ||||
| 		pm_qos_update_request(&vpp->vpp_mif_qos, 0); | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| void bts_send_bw(struct vpp_dev *vpp, bool enable) | ||||
| { | ||||
| 	struct decon_win_config *config = vpp->config; | ||||
| 	u8 vpp_type; | ||||
| 	enum vpp_bw_type bw_type; | ||||
| 
 | ||||
| 	if (is_rotation(config)) { | ||||
| 		if (config->src.w * config->src.h >= FULLHD_SRC) | ||||
| 			bw_type = BW_FULLHD_ROT; | ||||
| 		else | ||||
| 			bw_type = BW_ROT; | ||||
| 	} else { | ||||
| 		bw_type = BW_DEFAULT; | ||||
| 	} | ||||
| 
 | ||||
| 	vpp_type = vpp->id + ENUM_OFFSET; | ||||
| 
 | ||||
| 	if (enable) { | ||||
| 		exynos_update_media_scenario(vpp_type, vpp->cur_bw, bw_type); | ||||
| 	} else { | ||||
| 		exynos_update_media_scenario(vpp_type, 0, BW_DEFAULT); | ||||
| 		vpp->prev_bw = vpp->cur_bw = 0; | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| void bts_add_request(struct decon_device *decon) | ||||
| { | ||||
| 	pm_qos_add_request(&decon->mif_qos, PM_QOS_BUS_THROUGHPUT, 0); | ||||
| 	pm_qos_add_request(&decon->disp_qos, PM_QOS_DISPLAY_THROUGHPUT, 0); | ||||
| 	pm_qos_add_request(&decon->int_qos, PM_QOS_DEVICE_THROUGHPUT, 0); | ||||
| } | ||||
| 
 | ||||
| void bts_send_init(struct decon_device *decon) | ||||
| { | ||||
| 	pm_qos_update_request(&decon->mif_qos, 546000); | ||||
| } | ||||
| 
 | ||||
| void bts_send_release(struct decon_device *decon) | ||||
| { | ||||
| 	pm_qos_update_request(&decon->mif_qos, 0); | ||||
| 	pm_qos_update_request(&decon->disp_qos, 0); | ||||
| 	pm_qos_update_request(&decon->int_qos, 0); | ||||
| 	decon->disp_cur = decon->disp_prev = 0; | ||||
| } | ||||
| 
 | ||||
| void bts_remove_request(struct decon_device *decon) | ||||
| { | ||||
| 	pm_qos_remove_request(&decon->mif_qos); | ||||
| 	pm_qos_remove_request(&decon->disp_qos); | ||||
| 	pm_qos_remove_request(&decon->int_qos); | ||||
| } | ||||
| 
 | ||||
| void bts_calc_bw(struct vpp_dev *vpp) | ||||
| { | ||||
| 	bts_disp_bw(vpp); | ||||
| 	bts_int_mif_bw(vpp); | ||||
| } | ||||
| 
 | ||||
| void bts_send_zero_bw(struct vpp_dev *vpp) | ||||
| { | ||||
| 	bts_send_bw(vpp, false); | ||||
| } | ||||
| 
 | ||||
| void bts_send_calc_bw(struct vpp_dev *vpp) | ||||
| { | ||||
| 	bts_send_bw(vpp, true); | ||||
| } | ||||
| #else | ||||
| void bts_add_request(struct decon_device *decon){ return; } | ||||
| void bts_send_init(struct decon_device *decon){ return; } | ||||
| void bts_send_release(struct decon_device *decon){ return; } | ||||
| void bts_remove_request(struct decon_device *decon){ return; } | ||||
| 
 | ||||
| void bts_calc_bw(struct vpp_dev *vpp){ return; } | ||||
| void bts_send_calc_bw(struct vpp_dev *vpp){ return; } | ||||
| void bts_send_zero_bw(struct vpp_dev *vpp){ return; } | ||||
| void bts_mif_lock(struct vpp_dev *vpp){ return; } | ||||
| #endif | ||||
| 
 | ||||
| struct decon_init_bts decon_init_bts_control = { | ||||
| 	.bts_add		= bts_add_request, | ||||
| 	.bts_set_init		= bts_send_init, | ||||
| 	.bts_release_init	= bts_send_release, | ||||
| 	.bts_remove		= bts_remove_request, | ||||
| }; | ||||
| 
 | ||||
| struct decon_bts decon_bts_control = { | ||||
| 	.bts_get_bw		= bts_calc_bw, | ||||
| 	.bts_set_calc_bw	= bts_send_calc_bw, | ||||
| 	.bts_set_zero_bw	= bts_send_zero_bw, | ||||
| 	.bts_set_rot_mif	= bts_mif_lock, | ||||
| }; | ||||
							
								
								
									
										64
									
								
								drivers/video/fbdev/exynos/decon_8890/decon_bts.h
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										64
									
								
								drivers/video/fbdev/exynos/decon_8890/decon_bts.h
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,64 @@ | |||
| /* linux/drivers/video/exynos/decon/decon_bts.h
 | ||||
|  * | ||||
|  * Copyright (c) 2015 Samsung Electronics Co., Ltd. | ||||
|  *		http://www.samsung.com
 | ||||
|  * | ||||
|  * header file for Samsung EXYNOS5 SoC series DECON driver | ||||
| 
 | ||||
|  * 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. | ||||
|  */ | ||||
| 
 | ||||
| #ifndef DECON_BTS_H_ | ||||
| #define DECON_BTS_H_ | ||||
| 
 | ||||
| #include <linux/clk-provider.h> | ||||
| #include <linux/clk.h> | ||||
| 
 | ||||
| #include "decon.h" | ||||
| #include "vpp/vpp.h" | ||||
| 
 | ||||
| #define call_bts_ops(q, op, args...)				\ | ||||
| 	(((q)->bts_ops->op) ? ((q)->bts_ops->op(args)) : 0) | ||||
| 
 | ||||
| #define call_init_ops(q, op, args...)				\ | ||||
| 		(((q)->bts_init_ops->op) ? ((q)->bts_init_ops->op(args)) : 0) | ||||
| 
 | ||||
| extern struct decon_bts decon_bts_control; | ||||
| extern struct decon_init_bts decon_init_bts_control; | ||||
| 
 | ||||
| struct decon_init_bts { | ||||
| 	void	(*bts_add)(struct decon_device *decon); | ||||
| 	void	(*bts_set_init)(struct decon_device *decon); | ||||
| 	void	(*bts_release_init)(struct decon_device *decon); | ||||
| 	void	(*bts_remove)(struct decon_device *decon); | ||||
| }; | ||||
| 
 | ||||
| struct decon_bts { | ||||
| 	void	(*bts_get_bw)(struct vpp_dev *vpp); | ||||
| 	void	(*bts_set_calc_bw)(struct vpp_dev *vpp); | ||||
| 	void	(*bts_set_zero_bw)(struct vpp_dev *vpp); | ||||
| 	void	(*bts_set_rot_mif)(struct vpp_dev *vpp); | ||||
| }; | ||||
| 
 | ||||
| /* You should sync between enum init value of enum 'VPP0 = 2' and bts_media_type in bts driver */ | ||||
| enum disp_media_type { | ||||
| 	VPP0 = 2, | ||||
| 	VPP1, | ||||
| 	VPP2, | ||||
| 	VPP3, | ||||
| 	VPP4, | ||||
| 	VPP5, | ||||
| 	VPP6, | ||||
| 	VPP7, | ||||
| 	VPP8, | ||||
| }; | ||||
| 
 | ||||
| #define is_rotation(config) (config->vpp_parm.rot >= VPP_ROT_90) | ||||
| #define is_yuv(config) ((config->format >= DECON_PIXEL_FORMAT_NV16) && (config->format < DECON_PIXEL_FORMAT_MAX)) | ||||
| #define is_rgb(config) ((config->format >= DECON_PIXEL_FORMAT_ARGB_8888) && (config->format <= DECON_PIXEL_FORMAT_RGB_565)) | ||||
| #define is_scaling(vpp) ((vpp->h_ratio != (1 << 20)) || (vpp->v_ratio != (1 << 20))) | ||||
| #define is_scale_down(vpp) ((vpp->h_ratio > (1 << 20)) || (vpp->v_ratio > (1 << 20))) | ||||
| 
 | ||||
| #endif | ||||
							
								
								
									
										313
									
								
								drivers/video/fbdev/exynos/decon_8890/decon_common.h
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										313
									
								
								drivers/video/fbdev/exynos/decon_8890/decon_common.h
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,313 @@ | |||
| /*
 | ||||
|  * decon_common.h | ||||
|  * Copyright (c) 2014 Samsung Electronics Co., Ltd. | ||||
|  *		http://www.samsung.com
 | ||||
|  * | ||||
|  * Header file for Exynos DECON driver for exynos8890 | ||||
|  * | ||||
|  * 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. | ||||
| */ | ||||
| 
 | ||||
| #ifndef ___SAMSUNG_DECON_COMMON_H__ | ||||
| #define ___SAMSUNG_DECON_COMMON_H__ | ||||
| 
 | ||||
| #include "./panels/decon_lcd.h" | ||||
| 
 | ||||
| #define MAX_DECON_WIN		8 | ||||
| #define MAX_VPP_SUBDEV		9 | ||||
| #define SHADOW_UPDATE_TIMEOUT	(300 * 1000) /* 300ms */ | ||||
| 
 | ||||
| enum decon_trig_mode { | ||||
| 	DECON_HW_TRIG = 0, | ||||
| 	DECON_SW_TRIG | ||||
| }; | ||||
| 
 | ||||
| enum decon_output_type { | ||||
| 	DECON_OUT_DSI = 0, | ||||
| 	DECON_OUT_EDP, | ||||
| 	DECON_OUT_HDMI, | ||||
| 	DECON_OUT_WB, | ||||
| 	DECON_OUT_TUI | ||||
| }; | ||||
| 
 | ||||
| enum decon_dsi_mode { | ||||
| 	DSI_MODE_SINGLE = 0, | ||||
| 	DSI_MODE_DUAL_DSI, | ||||
| 	DSI_MODE_DUAL_DISPLAY, | ||||
| 	DSI_MODE_NONE | ||||
| }; | ||||
| 
 | ||||
| enum decon_hold_scheme { | ||||
| 	/*  should be set to this value in case of DSIM video mode */ | ||||
| 	DECON_VCLK_HOLD_ONLY		= 0x00, | ||||
| 	/*  should be set to this value in case of DSIM command mode */ | ||||
| 	DECON_VCLK_RUNNING_VDEN_DISABLE = 0x01, | ||||
| 	DECON_VCLK_HOLD_VDEN_DISABLE	= 0x02, | ||||
| 	/*  should be set to this value in case of HDMI, eDP */ | ||||
| 	DECON_VCLK_NOT_AFFECTED		= 0x03, | ||||
| }; | ||||
| 
 | ||||
| enum decon_rgb_order { | ||||
| 	DECON_RGB = 0x0, | ||||
| 	DECON_GBR = 0x1, | ||||
| 	DECON_BRG = 0x2, | ||||
| 	DECON_BGR = 0x4, | ||||
| 	DECON_RBG = 0x5, | ||||
| 	DECON_GRB = 0x6, | ||||
| }; | ||||
| 
 | ||||
| /* Porter Duff Compositing Operators */ | ||||
| enum decon_win_func { | ||||
| 	PD_FUNC_CLEAR			= 0x0, | ||||
| 	PD_FUNC_COPY			= 0x1, | ||||
| 	PD_FUNC_DESTINATION		= 0x2, | ||||
| 	PD_FUNC_SOURCE_OVER		= 0x3, | ||||
| 	PD_FUNC_DESTINATION_OVER	= 0x4, | ||||
| 	PD_FUNC_SOURCE_IN		= 0x5, | ||||
| 	PD_FUNC_DESTINATION_IN		= 0x6, | ||||
| 	PD_FUNC_SOURCE_OUT		= 0x7, | ||||
| 	PD_FUNC_DESTINATION_OUT		= 0x8, | ||||
| 	PD_FUNC_SOURCE_A_TOP		= 0x9, | ||||
| 	PD_FUNC_DESTINATION_A_TOP	= 0xa, | ||||
| 	PD_FUNC_XOR			= 0xb, | ||||
| 	PD_FUNC_PLUS			= 0xc, | ||||
| 	PD_FUNC_LEGACY			= 0xd, | ||||
| }; | ||||
| 
 | ||||
| enum decon_win_alpha_sel { | ||||
| 	/*  for plane blending */ | ||||
| 	W_ALPHA_SEL_F_ALPAH0 = 0, | ||||
| 	W_ALPHA_SEL_F_ALPAH1 = 1, | ||||
| 	/*  for pixel blending */ | ||||
| 	W_ALPHA_SEL_F_BYAEN = 2, | ||||
| 	/*  for multiplied alpha */ | ||||
| 	W_ALPHA_SEL_F_BYMUL = 4, | ||||
| }; | ||||
| 
 | ||||
| enum decon_set_trig { | ||||
| 	DECON_TRIG_DISABLE = 0, | ||||
| 	DECON_TRIG_ENABLE | ||||
| }; | ||||
| 
 | ||||
| enum decon_idma_type { | ||||
| 	IDMA_G0 = 0,	/* Dedicated to WIN7 */ | ||||
| 	IDMA_G1, | ||||
| 	IDMA_VG0, | ||||
| 	IDMA_VG1, | ||||
| 	IDMA_G2, | ||||
| 	IDMA_G3, | ||||
| 	IDMA_VGR0, | ||||
| 	IDMA_VGR1, | ||||
| 	ODMA_WB, | ||||
| 	IDMA_G0_S, | ||||
| }; | ||||
| 
 | ||||
| struct decon_mode_info { | ||||
| 	enum decon_psr_mode psr_mode; | ||||
| 	enum decon_trig_mode trig_mode; | ||||
| 	enum decon_output_type out_type; | ||||
| 	enum decon_dsi_mode dsi_mode; | ||||
| }; | ||||
| 
 | ||||
| struct decon_param { | ||||
| 	struct decon_mode_info psr; | ||||
| 	struct decon_lcd *lcd_info; | ||||
| 	u32 nr_windows; | ||||
| 	void __iomem *disp_ss_regs; | ||||
| }; | ||||
| 
 | ||||
| 
 | ||||
| struct decon_window_regs { | ||||
| 	u32 wincon; | ||||
| 	u32 start_pos; | ||||
| 	u32 end_pos; | ||||
| 	u32 colormap; | ||||
| 	u32 start_time; | ||||
| 	u32 pixel_count; | ||||
| 
 | ||||
| 	/* OS used */ | ||||
| 	u32 whole_w; | ||||
| 	u32 whole_h; | ||||
| 	u32 offset_x; | ||||
| 	u32 offset_y; | ||||
| 	u32 winmap_state; | ||||
| 
 | ||||
| 	enum decon_idma_type type; | ||||
| }; | ||||
| 
 | ||||
| /* To find a proper CLOCK ratio */ | ||||
| enum decon_clk_id { | ||||
| 	CLK_ID_VCLK = 0, | ||||
| 	CLK_ID_ECLK, | ||||
| 	CLK_ID_ACLK, | ||||
| 	CLK_ID_PCLK, | ||||
| 	CLK_ID_DPLL, /* DISP_PLL */ | ||||
| 	CLK_ID_RESOLUTION, | ||||
| 	CLK_ID_MIC_RATIO, | ||||
| 	CLK_ID_DSC_RATIO, | ||||
| 	CLK_ID_MAX, | ||||
| }; | ||||
| 
 | ||||
| struct decon_clocks { | ||||
| 	unsigned long decon[CLK_ID_DPLL + 1]; | ||||
| }; | ||||
| 
 | ||||
| enum decon_data_path { | ||||
| 	/* BLENDER-OUT -> No Comp -> SPLITTER(bypass) -> u0_FF -> u0_DISPIF */ | ||||
| 	DATAPATH_NOCOMP_SPLITTERBYPASS_U0FF_DISP0		= 0x01, | ||||
| 	/* BLENDER-OUT -> No Comp -> SPLITTER(bypass) -> u1_FF -> u1_DISPIF */ | ||||
| 	DATAPATH_NOCOMP_SPLITTERBYPASS_U1FF_DISP1		= 0x02, | ||||
| 	/* BLENDER-OUT -> No Comp -> SPLITTER(split) -> u0_FF/u1_FF -> u0_DISPIF/u1_DISPIF */ | ||||
| 	DATAPATH_NOCOMP_SPLITTER_U0FFU1FF_DISP0DISP1		= 0x03, | ||||
| 	/* BLENDER-OUT -> MIC -> SPLITTER(bypass) -> u0_FF -> u0_DISPIF */ | ||||
| 	DATAPATH_MIC_SPLITTERBYPASS_U0FF_DISP0			= 0x09, | ||||
| 	/* BLENDER-OUT -> MIC -> SPLITTER(bypass) -> u1_FF -> u1_DISPIF */ | ||||
| 	DATAPATH_MIC_SPLITTERBYPASS_U1FF_DISP1			= 0x0A, | ||||
| 	/* BLENDER-OUT -> MIC -> SPLITTER(split) -> u0_FF/u1_FF -> u0_DISPIF/u1_DISPIF */ | ||||
| 	DATAPATH_MIC_SPLITTER_U0FFU1FF_DISP0DISP1		= 0x0B, | ||||
| 	/* BLENDER-OUT -> DSCC,ENC0/1 -> u0_FF/u1_FF -> u_MERGER -> u0_DISPIF */ | ||||
| 	DATAPATH_DSCC_ENC0ENC1_U0FFU1FF_MERGER_DISP0		= 0x11, | ||||
| 	/* BLENDER-OUT -> DSCC,ENC0/1 -> u0_FF/u1_FF -> u_MERGER -> u1_DISPIF */ | ||||
| 	DATAPATH_DSCC_ENC0ENC1_U0FFU1FF_MERGER_DISP1		= 0x12, | ||||
| 	/* BLENDER-OUT -> DSCC,ENC0/1 -> u0_FF/u1_FF -> u0_DISPIF/u1_DISPIF */ | ||||
| 	DATAPATH_DSCC_ENC0ENC1_U0FFU1FF_DISP0DISP1		= 0x13, | ||||
| 	/* BLENDER-OUT -> ENC0 -> SPLITTER(bypass) -> u0_FF u0_DISPIF */ | ||||
| 	DATAPATH_ENC0_SPLITTERBYPASS_U0FF_DISP0			= 0x21, | ||||
| 	/* BLENDER-OUT -> ENC0 -> SPLITTER(bypass) -> u1_FF u1_DISPIF */ | ||||
| 	DATAPATH_ENC0_SPLITTERBYPASS_U1FF_DISP1			= 0x22, | ||||
| 	/* BLENDER-OUT -> ENC0 -> SPLITTER(split) -> u0_FF/u1_FF -> u0_DISPIF/u1_DISPIF */ | ||||
| 	DATAPATH_ENC0_SPLITTER_U0FFU1FF_DISP0DISP1		= 0x23, | ||||
| 	/* BLENDER-OUT -> No Comp -> SPLITTER(bypass) -> u0_FF -> POST-WB */ | ||||
| 	DATAPATH_NOCOMP_SPLITTERBYPASS_U0FF_POSTWB		= 0x04, | ||||
| 	/* BLENDER-OUT -> MIC -> SPLITTER(bypass) -> u0_FF -> POST-WB */ | ||||
| 	DATAPATH_MIC_SPLITTERBYPASS_U0FF_POSTWB			= 0x0C, | ||||
| 	/* BLENDER-OUT -> DSCC,ENC0/1 -> u0_FF/u1_FF -> u_MERGER -> POST-WB */ | ||||
| 	DATAPATH_DSCC_ENC0ENC1_U0FFU1FF_MERGER_POSTWB		= 0x14, | ||||
| 	/* BLENDER-OUT -> ENC0 -> SPLITTER(bypass) -> u0_FF -> POST-WB */ | ||||
| 	DATAPATH_ENC0_SPLITTERBYPASS_U0FF_POSTWB		= 0x24, | ||||
| 	/* u0_DISPIF (mapcolor mode) */ | ||||
| 	DATAPATH_DISP0_COLORMAP					= 0x41, | ||||
| 	/* u1_DISPIF (mapcolor mode) */ | ||||
| 	DATAPATH_DISP1_COLORMAP					= 0x42, | ||||
| 	/* u0_DISPIF/u1_DISPIF (mapcolor mode) */ | ||||
| 	DATAPATH_DISP0DISP1_ColorMap				= 0x43, | ||||
| 
 | ||||
| 	/* PRE-WB & BLENDER-OUT -> No Comp -> SPLITTER(bypass) -> u0_FF -> u0_DISPIF */ | ||||
| 	DATAPATH_PREWB_NOCOMP_SPLITTERBYPASS_U0FF_DISP0		= 0x81, | ||||
| 	/* PRE-WB & BLENDER-OUT -> No Comp -> SPLITTER(bypass) -> u1_FF -> u1_DISPIF */ | ||||
| 	DATAPATH_PREWB_NOCOMP_SPLITTERBYPASS_U1FF_DISP1		= 0x82, | ||||
| 	/* PRE-WB & BLENDER-OUT -> No Comp -> SPLITTER(split) -> u0_FF/u1_FF -> u0_DISPIF/u1_DISPIF */ | ||||
| 	DATAPATH_PREWB_NOCOMP_SPLITTER_U0FFU1FF_DISP0DISP1	= 0x83, | ||||
| 	/* PRE-WB & BLENDER-OUT -> MIC -> SPLITTER(bypass) -> u0_FF -> u0_DISPIF */ | ||||
| 	DATAPATH_PREWB_MIC_SPLITTERBYPASS_U0FF_DISP0		= 0x89, | ||||
| 	/* PRE-WB & BLENDER-OUT -> MIC -> SPLITTER(bypass) -> u1_FF -> u1_DISPIF */ | ||||
| 	DATAPATH_PREWB_MIC_SPLITTERBYPASS_U1FF_DISP1		= 0x8A, | ||||
| 	/* PRE-WB & BLENDER-OUT -> MIC -> SPLITTER(split) -> u0_FF/u1_FF -> u0_DISPIF/u1_DISPIF */ | ||||
| 	DATAPATH_PREWB_MIC_SPLITTER_U0FFU1FF_DISP0DISP1		= 0x8B, | ||||
| 	/* PRE-WB & BLENDER-OUT -> DSCC,ENC0/1 -> u0_FF/u1_FF -> u_MERGER -> u0_DISPIF */ | ||||
| 	DATAPATH_PREWB_DSCC_ENC0ENC1_U0FFU1FF_MERGER_DISP0	= 0x91, | ||||
| 	/* PRE-WB & BLENDER-OUT -> DSCC,ENC0/1 -> u0_FF/u1_FF -> u_MERGER -> u1_DISPIF */ | ||||
| 	DATAPATH_PREWB_DSCC_ENC0ENC1_U0FFU1FF_MERGER_DISP1	= 0x92, | ||||
| 	/* PRE-WB & BLENDER-OUT -> DSCC,ENC0/1 -> u0_FF/u1_FF -> u0_DISPIF/u1_DISPIF */ | ||||
| 	DATAPATH_PREWB_DSCC_ENC0ENC1_U0FFU1FF_DISP0DISP1	= 0x93, | ||||
| 	/* PRE-WB & BLENDER-OUT -> ENC0 -> SPLITTER(bypass) -> u0_FF -> u0_DISPIF */ | ||||
| 	DATAPATH_PREWB_ENC0_SPLITTERBYPASS_U0FF_DISP0		= 0xA1, | ||||
| 	/* PRE-WB & BLENDER-OUT -> ENC0 -> SPLITTER(bypass) -> u1_FF -> u1_DISPIF */ | ||||
| 	DATAPATH_PREWB_ENC0_SPLITTERBYPASS_U1FF_DISP1		= 0xA2, | ||||
| 	/* PRE-WB & BLENDER-OUT -> ENC0 -> SPLITTER(split) -> u0_FF/u1_FF -> u0_DISPIF/u1_DISPIF */ | ||||
| 	DATAPATH_PREWB_ENC0_SPLITTER_U0FFU1FF_DISP0DISP1	= 0xA3, | ||||
| 	/* PRE-WB only */ | ||||
| 	DATAPATH_PREWB_ONLY					= 0xC0, | ||||
| }; | ||||
| 
 | ||||
| enum decon_s_data_path { | ||||
| 	/*  BLENDER-OUT -> No Comp -> u0_FF -> u0_DISPIF */ | ||||
| 	DECONS_DATAPATH_NOCOMP_U0FF_DISP0			= 0x01, | ||||
| 	/*  BLENDER-OUT -> No Comp -> u0_FF -> POST_WB */ | ||||
| 	DECONS_DATAPATH_NOCOMP_U0FF_POSTWB			= 0x04, | ||||
| 	/*  BLENDER-OUT -> ENC1 -> u0_FF --> u0_DISPIF */ | ||||
| 	DECONS_DATAPATH_ENC0_U0FF_DISP0				= 0x21, | ||||
| 	/*  BLENDER-OUT -> ENC1 -> u0_FF -> POST_WB */ | ||||
| 	DECONS_DATAPATH_ENC0_U0FF_POSTWB			= 0x24, | ||||
| 	/*  u0_DISPIF (mapcolor mode) */ | ||||
| 	DECONS_DATAPATH_DISP0_COLORMAP				= 0x41, | ||||
| 	/*  PRE_WB & BLENDER-OUT -> No Comp -> u0_FF -> u0_DISPIF */ | ||||
| 	DECONS_DATAPATH_PREWB_NOCOMP_U0FF_DISP0			= 0x81, | ||||
| 	/*  PRE_WB & BLENDER-OUT -> ENC1 -> u0_FF -> u0_DISPIF */ | ||||
| 	DECONS_DATAPATH_PREWB_ENC0_U0FF_DISP0			= 0xA1, | ||||
| 	/*  PRE_WB only */ | ||||
| 	DECONS_DATAPATH_PREWB_ONLY				= 0xC0, | ||||
| }; | ||||
| 
 | ||||
| enum decon_enhance_path { | ||||
| 	ENHANCEPATH_ENHANCE_ALL_OFF	= 0x0, | ||||
| 	ENHANCEPATH_DITHER_ON		= 0x1, | ||||
| 	ENHANCEPATH_DPU_ON		= 0x2, | ||||
| 	ENHANCEPATH_DPU_DITHER_ON	= 0x3, | ||||
| 	ENHANCEPATH_MDNIE_ON		= 0x4, | ||||
| 	ENHANCEPATH_MDNIE_DITHER_ON	= 0x5, | ||||
| }; | ||||
| 
 | ||||
| 
 | ||||
| /* CAL APIs list */ | ||||
| int decon_reg_init(u32 id, u32 dsi_idx, struct decon_param *p); | ||||
| void decon_reg_init_probe(u32 id, u32 dsi_idx, struct decon_param *p); | ||||
| int decon_reg_start(u32 id, struct decon_mode_info *psr); | ||||
| int decon_reg_stop(u32 id, u32 dsi_idx, struct decon_mode_info *psr); | ||||
| void decon_reg_release_resource(u32 id, struct decon_mode_info *psr); | ||||
| void decon_reg_set_int(u32 id, struct decon_mode_info *psr, u32 en); | ||||
| void decon_reg_set_window_control(u32 id, int win_idx, struct decon_window_regs *regs, u32 winmap_en); | ||||
| void decon_reg_update_req_and_unmask(u32 id, struct decon_mode_info *psr); | ||||
| int decon_reg_wait_update_done_and_mask(u32 id, struct decon_mode_info *psr, u32 timeout); | ||||
| void decon_reg_set_trigger(u32 id, struct decon_mode_info *psr, | ||||
| 			enum decon_set_trig en); | ||||
| int decon_reg_wait_for_update_timeout(u32 id, unsigned long timeout); | ||||
| int decon_reg_wait_for_window_update_timeout(u32 id, u32 win_idx, unsigned long timeout); | ||||
| int decon_reg_get_interrupt_and_clear(u32 id); | ||||
| 
 | ||||
| /* CAL raw functions list */ | ||||
| void decon_reg_set_disp_ss_cfg(u32 id, void __iomem *disp_ss_regs, u32 dsi_idx, struct decon_mode_info *psr); | ||||
| int decon_reg_reset(u32 id); | ||||
| void decon_reg_set_clkgate_mode(u32 id, u32 en); | ||||
| void decon_reg_set_vclk_freerun(u32 id, u32 en); | ||||
| void decon_reg_set_vclk_divider(u32 id, u32 denom, u32 num); | ||||
| void decon_reg_set_eclk_divider(u32 id, u32 denom, u32 num); | ||||
| void decon_reg_set_sram_share(u32 id, u32 en); | ||||
| void decon_reg_set_data_path(u32 id, enum decon_data_path data_path, enum decon_enhance_path enhance_path); | ||||
| void decon_reg_get_data_path(u32 id, enum decon_data_path *data_path, enum decon_enhance_path *enhance_path); | ||||
| void decon_reg_set_operation_mode(u32 id, enum decon_psr_mode mode); | ||||
| void decon_reg_set_blender_bg_image_size(u32 id, enum decon_dsi_mode dsi_mode, struct decon_lcd *lcd_info); | ||||
| void decon_reg_get_blender_bg_image_size(u32 id, u32 *p_width, u32 *p_height); | ||||
| void decon_reg_set_underrun_scheme(u32 id, enum decon_hold_scheme mode); | ||||
| void decon_reg_set_rgb_order(u32 id, enum decon_rgb_order order); | ||||
| void decon_reg_set_frame_fifo_size(u32 id, enum decon_dsi_mode dsi_mode, u32 width, u32 height); | ||||
| void decon_reg_set_splitter(u32 id, enum decon_dsi_mode dsi_mode, u32 width, u32 height); | ||||
| void decon_reg_set_dispif_porch(u32 id, int dsi_idx, struct decon_lcd *lcd_info); | ||||
| void decon_reg_set_dispif_size(u32 id, int dsi_idx, u32 width, u32 height); | ||||
| void decon_reg_get_dispif_size(u32 id, int dsi_idx, u32 *p_width, u32 *p_height); | ||||
| void decon_reg_set_comp_size(u32 id, enum decon_mic_comp_ratio cr, enum decon_dsi_mode dsi_mode, struct decon_lcd *lcd_info); | ||||
| void decon_reg_config_mic(u32 id, enum decon_dsi_mode dsi_mode, struct decon_lcd *lcd_info); | ||||
| void decon_reg_update_req_global(u32 id); | ||||
| void decon_reg_update_req_window(u32 id, u32 win_idx); | ||||
| void decon_reg_all_win_shadow_update_req(u32 id); | ||||
| void decon_reg_direct_on_off(u32 id, u32 en); | ||||
| void decon_reg_per_frame_off(u32 id); | ||||
| void decon_reg_configure_lcd(u32 id, enum decon_dsi_mode dsi_mode, struct decon_lcd *lcd_info); | ||||
| void decon_reg_configure_trigger(u32 id, enum decon_trig_mode mode); | ||||
| u32 decon_reg_get_linecnt(u32 id, int dispif_idx); | ||||
| int decon_reg_wait_linecnt_is_zero_timeout(u32 id, int dsi_idx, unsigned long timeout); | ||||
| u32 decon_reg_get_run_status(u32 id); | ||||
| int decon_reg_wait_run_status_timeout(u32 id, unsigned long timeout); | ||||
| void decon_reg_clear_int_all(u32 id); | ||||
| u32 decon_get_win_channel(u32 id, u32 win_idx, enum decon_idma_type type); | ||||
| void decon_reg_config_win_channel(u32 id, u32 win_idx, enum decon_idma_type type); | ||||
| int decon_reg_is_win_enabled(u32 id, int win_idx); | ||||
| u32 decon_reg_get_width(u32 id, int dsi_mode); | ||||
| u32 decon_reg_get_height(u32 id, int dsi_mode); | ||||
| void decon_reg_get_clock_ratio(struct decon_clocks *clks, struct decon_lcd *lcd_info); | ||||
| void decon_reg_set_partial_update(u32 id, enum decon_dsi_mode dsi_mode, | ||||
| 		struct decon_lcd *lcd_info); | ||||
| 
 | ||||
| #endif /* ___SAMSUNG_DECON_COMMON_H__ */ | ||||
							
								
								
									
										3764
									
								
								drivers/video/fbdev/exynos/decon_8890/decon_core.c
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										3764
									
								
								drivers/video/fbdev/exynos/decon_8890/decon_core.c
									
										
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load diff
											
										
									
								
							
							
								
								
									
										745
									
								
								drivers/video/fbdev/exynos/decon_8890/decon_dsi.c
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										745
									
								
								drivers/video/fbdev/exynos/decon_8890/decon_dsi.c
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,745 @@ | |||
| /*
 | ||||
|  * Copyright (c) 2014 Samsung Electronics Co., Ltd. | ||||
|  *		http://www.samsung.com
 | ||||
|  * | ||||
|  * Core file for Samsung EXYNOS DECON driver | ||||
|  * | ||||
|  * 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. | ||||
| */ | ||||
| 
 | ||||
| #include <linux/of_gpio.h> | ||||
| #include <linux/of.h> | ||||
| #include <linux/clk-provider.h> | ||||
| #include <linux/pm_runtime.h> | ||||
| #include <linux/exynos_iovmm.h> | ||||
| #include <linux/of_address.h> | ||||
| #include <linux/clk-private.h> | ||||
| 
 | ||||
| #include <media/v4l2-subdev.h> | ||||
| 
 | ||||
| #include "decon.h" | ||||
| #include "dsim.h" | ||||
| #include "decon_helper.h" | ||||
| 
 | ||||
| int create_link_mipi(struct decon_device *decon, int id) | ||||
| { | ||||
| 	int i, ret = 0; | ||||
| 	int n_pad = decon->n_sink_pad + decon->n_src_pad; | ||||
| 	int flags = 0; | ||||
| 	char err[80]; | ||||
| 	struct exynos_md *md = decon->mdev; | ||||
| 
 | ||||
| 	if (IS_ERR_OR_NULL(md->dsim_sd[id])) { | ||||
| 		decon_err("failed to get subdev of dsim%d\n", decon->id); | ||||
| 		return -EINVAL; | ||||
| 	} | ||||
| 
 | ||||
| 	flags = MEDIA_LNK_FL_ENABLED; | ||||
| 	for (i = decon->n_sink_pad; i < n_pad; i++) { | ||||
| 		ret = media_entity_create_link(&decon->sd.entity, i, | ||||
| 				&md->dsim_sd[id]->entity, 0, flags); | ||||
| 		if (ret) { | ||||
| 			snprintf(err, sizeof(err), "%s --> %s", | ||||
| 					decon->sd.entity.name, | ||||
| 					decon->output_sd->entity.name); | ||||
| 			return ret; | ||||
| 		} | ||||
| 
 | ||||
| 		decon_info("%s[%d] --> [0]%s link is created successfully\n", | ||||
| 				decon->sd.entity.name, i, | ||||
| 				decon->output_sd->entity.name); | ||||
| 	} | ||||
| 
 | ||||
| 	return ret; | ||||
| } | ||||
| 
 | ||||
| int find_subdev_mipi(struct decon_device *decon, int id) | ||||
| { | ||||
| 	struct exynos_md *md; | ||||
| 
 | ||||
| 	md = (struct exynos_md *)module_name_to_driver_data(MDEV_MODULE_NAME); | ||||
| 	if (!md) { | ||||
| 		decon_err("failed to get mdev device(%d)\n", decon->id); | ||||
| 		return -ENODEV; | ||||
| 	} | ||||
| 
 | ||||
| 	decon->output_sd = md->dsim_sd[id]; | ||||
| 	decon->out_type = DECON_OUT_DSI; | ||||
| 	decon->out_idx = id; | ||||
| 
 | ||||
| 	if (IS_ERR_OR_NULL(decon->output_sd)) | ||||
| 		decon_warn("couldn't find dsim%d subdev\n", id); | ||||
| 
 | ||||
| 	v4l2_subdev_call(decon->output_sd, core, ioctl, DSIM_IOC_GET_LCD_INFO, NULL); | ||||
| 	decon->lcd_info = (struct decon_lcd *)v4l2_get_subdev_hostdata(decon->output_sd); | ||||
| 	if (IS_ERR_OR_NULL(decon->lcd_info)) { | ||||
| 		decon_err("failed to get lcd information\n"); | ||||
| 		return -EINVAL; | ||||
| 	} | ||||
| 	decon_dbg("###lcd_info[hfp %d hbp %d hsa %d vfp %d vbp %d vsa %d xres %d yres %d\n", | ||||
| 		decon->lcd_info->hfp,  decon->lcd_info->hbp,  decon->lcd_info->hsa, | ||||
| 		 decon->lcd_info->vfp,  decon->lcd_info->vbp,  decon->lcd_info->vsa, | ||||
| 		 decon->lcd_info->xres,  decon->lcd_info->yres); | ||||
| 
 | ||||
| 	return 0; | ||||
| } | ||||
| 
 | ||||
| static u32 fb_visual(u32 bits_per_pixel, unsigned short palette_sz) | ||||
| { | ||||
| 	switch (bits_per_pixel) { | ||||
| 	case 32: | ||||
| 	case 24: | ||||
| 	case 16: | ||||
| 	case 12: | ||||
| 		return FB_VISUAL_TRUECOLOR; | ||||
| 	case 8: | ||||
| 		if (palette_sz >= 256) | ||||
| 			return FB_VISUAL_PSEUDOCOLOR; | ||||
| 		else | ||||
| 			return FB_VISUAL_TRUECOLOR; | ||||
| 	case 1: | ||||
| 		return FB_VISUAL_MONO01; | ||||
| 	default: | ||||
| 		return FB_VISUAL_PSEUDOCOLOR; | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| static inline u32 fb_linelength(u32 xres_virtual, u32 bits_per_pixel) | ||||
| { | ||||
| 	return (xres_virtual * bits_per_pixel) / 8; | ||||
| } | ||||
| 
 | ||||
| static u16 fb_panstep(u32 res, u32 res_virtual) | ||||
| { | ||||
| 	return res_virtual > res ? 1 : 0; | ||||
| } | ||||
| 
 | ||||
| int decon_set_par(struct fb_info *info) | ||||
| { | ||||
| 	struct fb_var_screeninfo *var = &info->var; | ||||
| 	struct decon_win *win = info->par; | ||||
| 	struct decon_device *decon = win->decon; | ||||
| 	struct decon_window_regs win_regs; | ||||
| 	int win_no = win->index; | ||||
| 
 | ||||
| 	memset(&win_regs, 0, sizeof(struct decon_window_regs)); | ||||
| 	dev_info(decon->dev, "setting framebuffer parameters\n"); | ||||
| 
 | ||||
| 	if (decon->state == DECON_STATE_OFF) | ||||
| 		return 0; | ||||
| 
 | ||||
| 	decon_lpd_block_exit(decon); | ||||
| 
 | ||||
| 	decon_reg_wait_for_update_timeout(decon->id, SHADOW_UPDATE_TIMEOUT); | ||||
| 	info->fix.visual = fb_visual(var->bits_per_pixel, 0); | ||||
| 
 | ||||
| 	info->fix.line_length = fb_linelength(var->xres_virtual, | ||||
| 			var->bits_per_pixel); | ||||
| 	info->fix.xpanstep = fb_panstep(var->xres, var->xres_virtual); | ||||
| 	info->fix.ypanstep = fb_panstep(var->yres, var->yres_virtual); | ||||
| 
 | ||||
| 	if (decon_reg_is_win_enabled(decon->id, win_no)) | ||||
| 		win_regs.wincon = WIN_CONTROL_EN_F; | ||||
| 	else | ||||
| 		win_regs.wincon = 0; | ||||
| 
 | ||||
| 	win_regs.wincon |= wincon(var->transp.length, 0, 0xFF, | ||||
| 				0xFF, DECON_BLENDING_NONE); | ||||
| 	win_regs.start_pos = win_start_pos(0, 0); | ||||
| 	win_regs.end_pos = win_end_pos(0, 0, var->xres, var->yres); | ||||
| 	win_regs.pixel_count = (var->xres * var->yres); | ||||
| 	win_regs.whole_w = var->xoffset + var->xres; | ||||
| 	win_regs.whole_h = var->yoffset + var->yres; | ||||
| 	win_regs.offset_x = var->xoffset; | ||||
| 	win_regs.offset_y = var->yoffset; | ||||
| 	win_regs.type = decon->default_idma; | ||||
| 	decon_reg_set_window_control(decon->id, win_no, &win_regs, false); | ||||
| 
 | ||||
| 	decon_lpd_unblock(decon); | ||||
| 
 | ||||
| 	return 0; | ||||
| } | ||||
| EXPORT_SYMBOL(decon_set_par); | ||||
| 
 | ||||
| int decon_check_var(struct fb_var_screeninfo *var, struct fb_info *info) | ||||
| { | ||||
| 	struct decon_win *win = info->par; | ||||
| 	struct decon_device *decon = win->decon; | ||||
| 	int x, y; | ||||
| 	unsigned long long hz; | ||||
| 
 | ||||
| 	var->xres_virtual = max(var->xres_virtual, var->xres); | ||||
| 	var->yres_virtual = max(var->yres_virtual, var->yres); | ||||
| 
 | ||||
| 	if (!decon_validate_x_alignment(decon, 0, var->xres, | ||||
| 			var->bits_per_pixel)) | ||||
| 		return -EINVAL; | ||||
| 
 | ||||
| 	/* always ensure these are zero, for drop through cases below */ | ||||
| 	var->transp.offset = 0; | ||||
| 	var->transp.length = 0; | ||||
| 
 | ||||
| 	switch (var->bits_per_pixel) { | ||||
| 	case 1: | ||||
| 	case 2: | ||||
| 	case 4: | ||||
| 	case 8: | ||||
| 		var->red.offset		= 4; | ||||
| 		var->green.offset	= 2; | ||||
| 		var->blue.offset	= 0; | ||||
| 		var->red.length		= 5; | ||||
| 		var->green.length	= 3; | ||||
| 		var->blue.length	= 2; | ||||
| 		var->transp.offset	= 7; | ||||
| 		var->transp.length	= 1; | ||||
| 		break; | ||||
| 
 | ||||
| 	case 19: | ||||
| 		/* 666 with one bit alpha/transparency */ | ||||
| 		var->transp.offset	= 18; | ||||
| 		var->transp.length	= 1; | ||||
| 	case 18: | ||||
| 		var->bits_per_pixel	= 32; | ||||
| 
 | ||||
| 		/* 666 format */ | ||||
| 		var->red.offset		= 12; | ||||
| 		var->green.offset	= 6; | ||||
| 		var->blue.offset	= 0; | ||||
| 		var->red.length		= 6; | ||||
| 		var->green.length	= 6; | ||||
| 		var->blue.length	= 6; | ||||
| 		break; | ||||
| 
 | ||||
| 	case 16: | ||||
| 		/* 16 bpp, 565 format */ | ||||
| 		var->red.offset		= 11; | ||||
| 		var->green.offset	= 5; | ||||
| 		var->blue.offset	= 0; | ||||
| 		var->red.length		= 5; | ||||
| 		var->green.length	= 6; | ||||
| 		var->blue.length	= 5; | ||||
| 		break; | ||||
| 
 | ||||
| 	case 32: | ||||
| 	case 28: | ||||
| 	case 25: | ||||
| 		var->transp.length	= var->bits_per_pixel - 24; | ||||
| 		var->transp.offset	= 24; | ||||
| 		/* drop through */ | ||||
| 	case 24: | ||||
| 		/* our 24bpp is unpacked, so 32bpp */ | ||||
| 		var->bits_per_pixel	= 32; | ||||
| 		var->red.offset		= 16; | ||||
| 		var->red.length		= 8; | ||||
| 		var->green.offset	= 8; | ||||
| 		var->green.length	= 8; | ||||
| 		var->blue.offset	= 0; | ||||
| 		var->blue.length	= 8; | ||||
| 		break; | ||||
| 
 | ||||
| 	default: | ||||
| 		decon_err("invalid bpp %d\n", var->bits_per_pixel); | ||||
| 		return -EINVAL; | ||||
| 	} | ||||
| 
 | ||||
| 	if (decon->pdata->psr_mode == DECON_MIPI_COMMAND_MODE) { | ||||
| 		x = var->xres; | ||||
| 		y = var->yres; | ||||
| 	} else { | ||||
| 		x = var->xres + var->left_margin + var->right_margin + var->hsync_len; | ||||
| 		y = var->yres + var->upper_margin + var->lower_margin + var->vsync_len; | ||||
| 	} | ||||
| 	hz = 1000000000000ULL;		/* 1e12 picoseconds per second */ | ||||
| 
 | ||||
| 	hz += (x * y) / 2; | ||||
| 	do_div(hz, x * y);		/* divide by x * y with rounding */ | ||||
| 
 | ||||
| 	hz += var->pixclock / 2; | ||||
| 	do_div(hz, var->pixclock);	/* divide by pixclock with rounding */ | ||||
| 
 | ||||
| 	win->fps = hz; | ||||
| 	decon_dbg("xres:%d, yres:%d, v_xres:%d, v_yres:%d, bpp:%d, %lldhz\n", | ||||
| 			var->xres, var->yres, var->xres_virtual, | ||||
| 			var->yres_virtual, var->bits_per_pixel, hz); | ||||
| 
 | ||||
| 	return 0; | ||||
| } | ||||
| 
 | ||||
| static inline unsigned int chan_to_field(unsigned int chan, | ||||
| 					 struct fb_bitfield *bf) | ||||
| { | ||||
| 	chan &= 0xffff; | ||||
| 	chan >>= 16 - bf->length; | ||||
| 	return chan << bf->offset; | ||||
| } | ||||
| 
 | ||||
| int decon_setcolreg(unsigned regno, | ||||
| 			    unsigned red, unsigned green, unsigned blue, | ||||
| 			    unsigned transp, struct fb_info *info) | ||||
| { | ||||
| 	struct decon_win *win = info->par; | ||||
| 	struct decon_device *decon = win->decon; | ||||
| 	unsigned int val; | ||||
| 
 | ||||
| 	dev_dbg(decon->dev, "%s: win %d: %d => rgb=%d/%d/%d\n", | ||||
| 		__func__, win->index, regno, red, green, blue); | ||||
| 
 | ||||
| 	if (decon->state == DECON_STATE_OFF) | ||||
| 		return 0; | ||||
| 
 | ||||
| 	switch (info->fix.visual) { | ||||
| 	case FB_VISUAL_TRUECOLOR: | ||||
| 		/* true-colour, use pseudo-palette */ | ||||
| 
 | ||||
| 		if (regno < 16) { | ||||
| 			u32 *pal = info->pseudo_palette; | ||||
| 
 | ||||
| 			val  = chan_to_field(red,   &info->var.red); | ||||
| 			val |= chan_to_field(green, &info->var.green); | ||||
| 			val |= chan_to_field(blue,  &info->var.blue); | ||||
| 
 | ||||
| 			pal[regno] = val; | ||||
| 		} | ||||
| 		break; | ||||
| 	default: | ||||
| 		return 1;	/* unknown type */ | ||||
| 	} | ||||
| 
 | ||||
| 	return 0; | ||||
| } | ||||
| EXPORT_SYMBOL(decon_setcolreg); | ||||
| 
 | ||||
| int decon_pan_display(struct fb_var_screeninfo *var, struct fb_info *info) | ||||
| { | ||||
| 	struct decon_win *win = info->par; | ||||
| 	struct decon_device *decon = win->decon; | ||||
| 	struct v4l2_subdev *sd = NULL; | ||||
| 	struct decon_win_config config; | ||||
| 	int ret = 0; | ||||
| 	int shift = 0; | ||||
| 	struct decon_mode_info psr; | ||||
| 
 | ||||
| 	decon_lpd_block_exit(decon); | ||||
| 
 | ||||
| 	decon_set_par(info); | ||||
| 
 | ||||
| 	decon->vpp_usage_bitmask |= (1 << decon->default_idma); | ||||
| 	decon->vpp_used[decon->default_idma] = true; | ||||
| 	memset(&config, 0, sizeof(struct decon_win_config)); | ||||
| 	switch (var->bits_per_pixel) { | ||||
| 	case 16: | ||||
| 		config.format = DECON_PIXEL_FORMAT_RGB_565; | ||||
| 		shift = 2; | ||||
| 		break; | ||||
| 	case 24: | ||||
| 	case 32: | ||||
| 		config.format = DECON_PIXEL_FORMAT_BGRA_8888; | ||||
| 		shift = 4; | ||||
| 		break; | ||||
| 	default: | ||||
| 		decon_err("%s: bits_per_pixel %d\n", __func__, var->bits_per_pixel); | ||||
| 	} | ||||
| 
 | ||||
| 	config.vpp_parm.addr[0] = info->fix.smem_start; | ||||
| 	config.src.x =  var->xoffset >> shift; | ||||
| 	config.src.y =  var->yoffset; | ||||
| 	config.src.w = var->xres; | ||||
| 	config.src.h = var->yres; | ||||
| 	config.src.f_w = var->xres; | ||||
| 	config.src.f_h = var->yres; | ||||
| 	config.dst.w = config.src.w; | ||||
| 	config.dst.h = config.src.h; | ||||
| 	config.dst.f_w = config.src.f_w; | ||||
| 	config.dst.f_h = config.src.f_h; | ||||
| 	sd = decon->mdev->vpp_sd[decon->default_idma]; | ||||
| 	if (v4l2_subdev_call(sd, core, ioctl, VPP_WIN_CONFIG, &config)) { | ||||
| 		decon_err("%s: Failed to config VPP-%d\n", __func__, win->vpp_id); | ||||
| 		decon->vpp_usage_bitmask &= ~(1 << win->vpp_id); | ||||
| 		decon->vpp_err_stat[win->vpp_id] = true; | ||||
| 	} | ||||
| 
 | ||||
| 	decon_reg_update_req_window(decon->id, win->index); | ||||
| 
 | ||||
| 	decon_to_psr_info(decon, &psr); | ||||
| 	decon_reg_start(decon->id, &psr); | ||||
| 	decon_wait_for_vsync(decon, VSYNC_TIMEOUT_MSEC); | ||||
| 
 | ||||
| 	if (decon_reg_wait_update_done_and_mask(decon->id, &psr, SHADOW_UPDATE_TIMEOUT) | ||||
| 			< 0) | ||||
| 		decon_err("%s: wait_for_update_timeout\n", __func__); | ||||
| 
 | ||||
| 	decon_lpd_unblock(decon); | ||||
| 	return ret; | ||||
| } | ||||
| EXPORT_SYMBOL(decon_pan_display); | ||||
| 
 | ||||
| int decon_mmap(struct fb_info *info, struct vm_area_struct *vma) | ||||
| { | ||||
| #ifdef CONFIG_ION_EXYNOS | ||||
| 	int ret; | ||||
| 	struct decon_win *win = info->par; | ||||
| 	vma->vm_page_prot = pgprot_writecombine(vma->vm_page_prot); | ||||
| 
 | ||||
| 	ret = dma_buf_mmap(win->dma_buf_data[0].dma_buf, vma, 0); | ||||
| 
 | ||||
| 	return ret; | ||||
| #else | ||||
| 	return 0; | ||||
| #endif | ||||
| } | ||||
| EXPORT_SYMBOL(decon_mmap); | ||||
| 
 | ||||
| static void decon_fb_missing_pixclock(struct decon_fb_videomode *win_mode, | ||||
| 		enum decon_psr_mode mode) | ||||
| { | ||||
| 	u64 pixclk = 1000000000000ULL; | ||||
| 	u32 div; | ||||
| 	u32 width, height; | ||||
| 
 | ||||
| 	if (mode == DECON_MIPI_COMMAND_MODE) { | ||||
| 		width = win_mode->videomode.xres; | ||||
| 		height = win_mode->videomode.yres; | ||||
| 	} else { | ||||
| 		width  = win_mode->videomode.left_margin + win_mode->videomode.hsync_len + | ||||
| 			win_mode->videomode.right_margin + win_mode->videomode.xres; | ||||
| 		height = win_mode->videomode.upper_margin + win_mode->videomode.vsync_len + | ||||
| 			win_mode->videomode.lower_margin + win_mode->videomode.yres; | ||||
| 	} | ||||
| 
 | ||||
| 	div = width * height * (win_mode->videomode.refresh ? : 60); | ||||
| 
 | ||||
| 	do_div(pixclk, div); | ||||
| 	win_mode->videomode.pixclock = pixclk; | ||||
| } | ||||
| 
 | ||||
| static void decon_parse_lcd_info(struct decon_device *decon) | ||||
| { | ||||
| 	int i; | ||||
| 	struct decon_lcd *lcd_info = decon->lcd_info; | ||||
| 
 | ||||
| 	for (i = 0; i < decon->pdata->max_win; i++) { | ||||
| 		decon->windows[i]->win_mode.videomode.left_margin = lcd_info->hbp; | ||||
| 		decon->windows[i]->win_mode.videomode.right_margin = lcd_info->hfp; | ||||
| 		decon->windows[i]->win_mode.videomode.upper_margin = lcd_info->vbp; | ||||
| 		decon->windows[i]->win_mode.videomode.lower_margin = lcd_info->vfp; | ||||
| 		decon->windows[i]->win_mode.videomode.hsync_len = lcd_info->hsa; | ||||
| 		decon->windows[i]->win_mode.videomode.vsync_len = lcd_info->vsa; | ||||
| 		decon->windows[i]->win_mode.videomode.xres = lcd_info->xres; | ||||
| 		decon->windows[i]->win_mode.videomode.yres = lcd_info->yres; | ||||
| 		decon->windows[i]->win_mode.width = lcd_info->width; | ||||
| 		decon->windows[i]->win_mode.height = lcd_info->height; | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| int decon_set_lcd_config(struct decon_device *decon) | ||||
| { | ||||
| 	struct fb_info *fbinfo; | ||||
| 	struct decon_fb_videomode *win_mode; | ||||
| 	int i, ret = 0; | ||||
| 
 | ||||
| 	decon_parse_lcd_info(decon); | ||||
| 	for (i = 0; i < decon->pdata->max_win; i++) { | ||||
| 		if (!decon->windows[i]) | ||||
| 			continue; | ||||
| 
 | ||||
| 		win_mode = &decon->windows[i]->win_mode; | ||||
| 		if (!win_mode->videomode.pixclock) | ||||
| 			decon_fb_missing_pixclock(win_mode, decon->pdata->psr_mode); | ||||
| 
 | ||||
| 		fbinfo = decon->windows[i]->fbinfo; | ||||
| 		fb_videomode_to_var(&fbinfo->var, &win_mode->videomode); | ||||
| 
 | ||||
| 		fbinfo->fix.type	= FB_TYPE_PACKED_PIXELS; | ||||
| 		fbinfo->fix.accel	= FB_ACCEL_NONE; | ||||
| 		fbinfo->fix.line_length = fb_linelength(fbinfo->var.xres_virtual, | ||||
| 					fbinfo->var.bits_per_pixel); | ||||
| 		fbinfo->var.activate	= FB_ACTIVATE_NOW; | ||||
| 		fbinfo->var.vmode	= FB_VMODE_NONINTERLACED; | ||||
| 		fbinfo->var.bits_per_pixel = LCD_DEFAULT_BPP; | ||||
| 		fbinfo->var.width	= win_mode->width; | ||||
| 		fbinfo->var.height	= win_mode->height; | ||||
| 
 | ||||
| 		ret = decon_check_var(&fbinfo->var, fbinfo); | ||||
| 		if (ret) | ||||
| 			return ret; | ||||
| 		decon_dbg("window[%d] verified parameters\n", i); | ||||
| 	} | ||||
| 
 | ||||
| 	return ret; | ||||
| } | ||||
| 
 | ||||
| irqreturn_t decon_fb_isr_for_eint(int irq, void *dev_id) | ||||
| { | ||||
| 	struct decon_device *decon = dev_id; | ||||
| 	struct decon_mode_info psr; | ||||
| 	ktime_t timestamp = ktime_get(); | ||||
| 
 | ||||
| 	DISP_SS_EVENT_LOG(DISP_EVT_TE_INTERRUPT, &decon->sd, timestamp); | ||||
| 
 | ||||
| 	spin_lock(&decon->slock); | ||||
| 
 | ||||
| 	if (decon->pdata->trig_mode == DECON_SW_TRIG) { | ||||
| 		decon_to_psr_info(decon, &psr); | ||||
| 		decon_reg_set_trigger(decon->id, &psr, DECON_TRIG_ENABLE); | ||||
| 	} | ||||
| 
 | ||||
| #ifdef CONFIG_DECON_LPD_DISPLAY | ||||
| 	if ((decon->state == DECON_STATE_ON) && (decon->out_type == DECON_OUT_DSI)) { | ||||
| 		if (decon_min_lock_cond(decon)) | ||||
| 			queue_work(decon->lpd_wq, &decon->lpd_work); | ||||
| 	} | ||||
| #endif | ||||
| 	decon->vsync_info.timestamp = timestamp; | ||||
| 	wake_up_interruptible_all(&decon->vsync_info.wait); | ||||
| 
 | ||||
| 	spin_unlock(&decon->slock); | ||||
| 
 | ||||
| 	return IRQ_HANDLED; | ||||
| } | ||||
| 
 | ||||
| int decon_config_eint_for_te(struct platform_device *pdev, struct decon_device *decon) | ||||
| { | ||||
| 	struct device *dev = decon->dev; | ||||
| 	int gpio; | ||||
| 	int ret = 0; | ||||
| 
 | ||||
| 	/* Get IRQ resource and register IRQ handler. */ | ||||
| 	gpio = of_get_gpio(dev->of_node, 0); | ||||
| 	if (gpio < 0) { | ||||
| 		decon_err("failed to get proper gpio number\n"); | ||||
| 		return -EINVAL; | ||||
| 	} | ||||
| 
 | ||||
| 	gpio = gpio_to_irq(gpio); | ||||
| 	decon->irq = gpio; | ||||
| 	ret = devm_request_irq(dev, gpio, decon_fb_isr_for_eint, | ||||
| 			  IRQF_TRIGGER_RISING, pdev->name, decon); | ||||
| 	decon->eint_status = 1; | ||||
| 
 | ||||
| 	return ret; | ||||
| } | ||||
| 
 | ||||
| static int decon_wait_for_vsync_thread(void *data) | ||||
| { | ||||
| 	struct decon_device *decon = data; | ||||
| 
 | ||||
| 	while (!kthread_should_stop()) { | ||||
| 		ktime_t timestamp = decon->vsync_info.timestamp; | ||||
| 		int ret = wait_event_interruptible(decon->vsync_info.wait, | ||||
| 			!ktime_equal(timestamp, decon->vsync_info.timestamp) && | ||||
| 			decon->vsync_info.active); | ||||
| 
 | ||||
| 		if (!ret) | ||||
| 			sysfs_notify(&decon->dev->kobj, NULL, "vsync"); | ||||
| 	} | ||||
| 
 | ||||
| 	return 0; | ||||
| } | ||||
| 
 | ||||
| static ssize_t decon_vsync_show(struct device *dev, | ||||
| 		struct device_attribute *attr, char *buf) | ||||
| { | ||||
| 	struct decon_device *decon = dev_get_drvdata(dev); | ||||
| 	return scnprintf(buf, PAGE_SIZE, "%llu\n", | ||||
| 			ktime_to_ns(decon->vsync_info.timestamp)); | ||||
| } | ||||
| 
 | ||||
| static DEVICE_ATTR(vsync, S_IRUGO, decon_vsync_show, NULL); | ||||
| 
 | ||||
| static ssize_t decon_psr_info(struct device *dev, | ||||
| 		struct device_attribute *attr, char *buf) | ||||
| { | ||||
| 	struct decon_device *decon = dev_get_drvdata(dev); | ||||
| 	return scnprintf(buf, PAGE_SIZE, "%d\n", decon->pdata->psr_mode); | ||||
| } | ||||
| 
 | ||||
| static DEVICE_ATTR(psr_info, S_IRUGO, decon_psr_info, NULL); | ||||
| 
 | ||||
| int decon_f_create_vsync_thread(struct decon_device *decon) | ||||
| { | ||||
| 	int ret = 0; | ||||
| 
 | ||||
| 	ret = device_create_file(decon->dev, &dev_attr_vsync); | ||||
| 	if (ret) { | ||||
| 		decon_err("failed to create vsync file\n"); | ||||
| 		return ret; | ||||
| 	} | ||||
| 
 | ||||
| 	decon->vsync_info.thread = kthread_run(decon_wait_for_vsync_thread, | ||||
| 			decon, "s3c-fb-vsync"); | ||||
| 	if (decon->vsync_info.thread == ERR_PTR(-ENOMEM)) { | ||||
| 		decon_err("failed to run vsync thread\n"); | ||||
| 		decon->vsync_info.thread = NULL; | ||||
| 	} | ||||
| 
 | ||||
| 	return ret; | ||||
| } | ||||
| 
 | ||||
| int decon_f_create_psr_thread(struct decon_device *decon) | ||||
| { | ||||
| 	int ret = 0; | ||||
| 
 | ||||
| 	ret = device_create_file(decon->dev, &dev_attr_psr_info); | ||||
| 	if (ret) { | ||||
| 		decon_err("failed to create psr info file\n"); | ||||
| 		return ret; | ||||
| 	} | ||||
| 
 | ||||
| 	return ret; | ||||
| } | ||||
| 
 | ||||
| void decon_f_destroy_vsync_thread(struct decon_device *decon) | ||||
| { | ||||
| 	device_remove_file(decon->dev, &dev_attr_vsync); | ||||
| } | ||||
| 
 | ||||
| void decon_f_destroy_psr_thread(struct decon_device *decon) | ||||
| { | ||||
| 	device_remove_file(decon->dev, &dev_attr_psr_info); | ||||
| } | ||||
| 
 | ||||
| /************* LPD funtions ************************/ | ||||
| u32 decon_reg_get_cam_status(void __iomem *cam_status) | ||||
| { | ||||
| 	if (cam_status) | ||||
| 		return readl(cam_status); | ||||
| 	else | ||||
| 		return 0xF; | ||||
| } | ||||
| 
 | ||||
| static int decon_enter_lpd(struct decon_device *decon) | ||||
| { | ||||
| 	int ret = 0; | ||||
| 
 | ||||
| #ifdef CONFIG_DECON_LPD_DISPLAY | ||||
| 	DISP_SS_EVENT_START(); | ||||
| 
 | ||||
| 	mutex_lock(&decon->lpd_lock); | ||||
| 
 | ||||
| 	if (decon_is_lpd_blocked(decon)) | ||||
| 		goto err2; | ||||
| 
 | ||||
| 	decon_lpd_block(decon); | ||||
| 	if ((decon->state == DECON_STATE_LPD) || | ||||
| 		(decon->state != DECON_STATE_ON)) { | ||||
| 		goto err; | ||||
| 	} | ||||
| 
 | ||||
| 	exynos_ss_printk("%s +\n", __func__); | ||||
| 	decon_lpd_trig_reset(decon); | ||||
| 	decon->state = DECON_STATE_LPD_ENT_REQ; | ||||
| 	decon_disable(decon); | ||||
| 	decon->state = DECON_STATE_LPD; | ||||
| 	exynos_ss_printk("%s -\n", __func__); | ||||
| 
 | ||||
| 	DISP_SS_EVENT_LOG(DISP_EVT_ENTER_LPD, &decon->sd, start); | ||||
| err: | ||||
| 	decon_lpd_unblock(decon); | ||||
| err2: | ||||
| 	mutex_unlock(&decon->lpd_lock); | ||||
| #endif | ||||
| 	return ret; | ||||
| } | ||||
| 
 | ||||
| int decon_exit_lpd(struct decon_device *decon) | ||||
| { | ||||
| 	int ret = 0; | ||||
| 
 | ||||
| #ifdef CONFIG_DECON_LPD_DISPLAY | ||||
| 	DISP_SS_EVENT_START(); | ||||
| 
 | ||||
| 	decon_lpd_block(decon); | ||||
| 	flush_workqueue(decon->lpd_wq); | ||||
| 	mutex_lock(&decon->lpd_lock); | ||||
| 
 | ||||
| 	if (decon->state != DECON_STATE_LPD) | ||||
| 		goto err; | ||||
| 
 | ||||
| 	exynos_ss_printk("%s +\n", __func__); | ||||
| 	decon->state = DECON_STATE_LPD_EXIT_REQ; | ||||
| 	decon_enable(decon); | ||||
| 	decon_lpd_trig_reset(decon); | ||||
| 	decon->state = DECON_STATE_ON; | ||||
| 	exynos_ss_printk("%s -\n", __func__); | ||||
| 
 | ||||
| 	DISP_SS_EVENT_LOG(DISP_EVT_EXIT_LPD, &decon->sd, start); | ||||
| err: | ||||
| 	decon_lpd_unblock(decon); | ||||
| 	mutex_unlock(&decon->lpd_lock); | ||||
| #endif | ||||
| 	return ret; | ||||
| } | ||||
| 
 | ||||
| int decon_lpd_block_exit(struct decon_device *decon) | ||||
| { | ||||
| 	int ret = 0; | ||||
| 
 | ||||
| 	if (!decon || !decon->lpd_init_status) | ||||
| 		return 0; | ||||
| 
 | ||||
| 	decon_lpd_block(decon); | ||||
| 	ret = decon_exit_lpd(decon); | ||||
| 
 | ||||
| 	return ret; | ||||
| } | ||||
| 
 | ||||
| #ifdef DECON_LPD_OPT | ||||
| int decon_lcd_off(struct decon_device *decon) | ||||
| { | ||||
| 	/* It cann't be used incase of PACKET_GO mode */ | ||||
| 	int ret; | ||||
| 
 | ||||
| 	decon_info("%s +\n", __func__); | ||||
| 
 | ||||
| 	decon_lpd_block(decon); | ||||
| 	flush_workqueue(decon->lpd_wq); | ||||
| 
 | ||||
| 	mutex_lock(&decon->lpd_lock); | ||||
| 
 | ||||
| 	ret = v4l2_subdev_call(decon->output_sd, core, ioctl, DSIM_IOC_LCD_OFF, NULL); | ||||
| 	if (ret < 0) | ||||
| 		decon_err("failed to turn off LCD\n"); | ||||
| 
 | ||||
| 	decon->state = DECON_STATE_OFF; | ||||
| 
 | ||||
| 	mutex_unlock(&decon->lpd_lock); | ||||
| 	decon_lpd_unblock(decon); | ||||
| 
 | ||||
| 	decon_info("%s -\n", __func__); | ||||
| 
 | ||||
| 	return 0; | ||||
| } | ||||
| #endif | ||||
| 
 | ||||
| static void decon_lpd_handler(struct work_struct *work) | ||||
| { | ||||
| 	struct decon_device *decon = | ||||
| 			container_of(work, struct decon_device, lpd_work); | ||||
| 
 | ||||
| 	if (!decon || !decon->lpd_init_status) | ||||
| 		return; | ||||
| 
 | ||||
| 	if (decon_lpd_enter_cond(decon)) | ||||
| 		decon_enter_lpd(decon); | ||||
| } | ||||
| 
 | ||||
| int decon_register_lpd_work(struct decon_device *decon) | ||||
| { | ||||
| 	mutex_init(&decon->lpd_lock); | ||||
| 
 | ||||
| 	atomic_set(&decon->lpd_trig_cnt, 0); | ||||
| 	atomic_set(&decon->lpd_block_cnt, 0); | ||||
| 
 | ||||
| 	decon->lpd_wq = create_singlethread_workqueue("decon_lpd"); | ||||
| 	if (decon->lpd_wq == NULL) { | ||||
| 		decon_err("%s:failed to create workqueue for LPD\n", __func__); | ||||
| 		return -ENOMEM; | ||||
| 	} | ||||
| 
 | ||||
| 	INIT_WORK(&decon->lpd_work, decon_lpd_handler); | ||||
| 	decon->lpd_init_status = true; | ||||
| 
 | ||||
| 	return 0; | ||||
| } | ||||
							
								
								
									
										260
									
								
								drivers/video/fbdev/exynos/decon_8890/decon_f.c
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										260
									
								
								drivers/video/fbdev/exynos/decon_8890/decon_f.c
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,260 @@ | |||
| /*
 | ||||
|  * Copyright (c) 2014 Samsung Electronics Co., Ltd. | ||||
|  *		http://www.samsung.com
 | ||||
|  * | ||||
|  * Core file for Samsung EXYNOS DECON driver | ||||
|  * | ||||
|  * 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. | ||||
| */ | ||||
| 
 | ||||
| #include <linux/of_gpio.h> | ||||
| #include <linux/of.h> | ||||
| #include <linux/clk-provider.h> | ||||
| #include <linux/pm_runtime.h> | ||||
| #include <linux/exynos_iovmm.h> | ||||
| #include <linux/of_address.h> | ||||
| #include <linux/clk-private.h> | ||||
| 
 | ||||
| #include <media/v4l2-subdev.h> | ||||
| 
 | ||||
| #include "../../../../soc/samsung/pwrcal/pwrcal.h" | ||||
| #include "../../../../soc/samsung/pwrcal/S5E8890/S5E8890-vclk.h" | ||||
| #include "decon.h" | ||||
| #include "dsim.h" | ||||
| #include "decon_helper.h" | ||||
| 
 | ||||
| static void decon_oneshot_underrun_log(struct decon_device *decon) | ||||
| { | ||||
| 	DISP_SS_EVENT_LOG(DISP_EVT_UNDERRUN, &decon->sd, ktime_set(0, 0)); | ||||
| 
 | ||||
| 	decon->underrun_stat.underrun_cnt++; | ||||
| 	if (decon->fifo_irq_status++ > UNDERRUN_FILTER_IDLE) | ||||
| 		return; | ||||
| 
 | ||||
| 	if (decon->underrun_stat.underrun_cnt > DECON_UNDERRUN_THRESHOLD) { | ||||
| 		decon_warn("[underrun]: (cnt %d), tot_bw %d, int_bw %d, disp_bw %d\n", | ||||
| 				decon->underrun_stat.underrun_cnt, | ||||
| 				decon->underrun_stat.prev_bw, | ||||
| 				decon->underrun_stat.prev_int_bw, | ||||
| 				decon->underrun_stat.prev_disp_bw); | ||||
| 		decon_warn("                  chmap(0x%08x), win(0x%lx), aclk(%ld)\n", | ||||
| 				decon->underrun_stat.chmap, | ||||
| 				decon->underrun_stat.used_windows, | ||||
| 				decon->underrun_stat.aclk / MHZ); | ||||
| 		decon->underrun_stat.underrun_cnt = 0; | ||||
| 	} | ||||
| 
 | ||||
| 	queue_work(decon->fifo_irq_wq, &decon->fifo_irq_work); | ||||
| } | ||||
| 
 | ||||
| static void decon_f_get_enabled_win(struct decon_device *decon) | ||||
| { | ||||
| 	int i; | ||||
| 
 | ||||
| 	decon->underrun_stat.used_windows = 0; | ||||
| 
 | ||||
| 	for (i = 0; i < MAX_DECON_WIN; ++i) | ||||
| 		if (decon_read(decon->id, (WIN_CONTROL(i)) + SHADOW_OFFSET) & WIN_CONTROL_EN_F) | ||||
| 			set_bit(i * 4, &decon->underrun_stat.used_windows); | ||||
| } | ||||
| 
 | ||||
| irqreturn_t decon_f_irq_handler(int irq, void *dev_data) | ||||
| { | ||||
| 	struct decon_device *decon = dev_data; | ||||
| 	u32 irq_sts_reg; | ||||
| 	ktime_t timestamp; | ||||
| 	u32 fifo_level = 0; | ||||
| 
 | ||||
| 	timestamp = ktime_get(); | ||||
| 
 | ||||
| 	spin_lock(&decon->slock); | ||||
| 	if ((decon->state == DECON_STATE_OFF) || | ||||
| 		(decon->state == DECON_STATE_LPD)) { | ||||
| 		goto irq_end; | ||||
| 	} | ||||
| 
 | ||||
| 	irq_sts_reg = decon_reg_get_interrupt_and_clear(decon->id); | ||||
| 
 | ||||
| 	if (irq_sts_reg & INTERRUPT_DISPIF_VSTATUS_INT_EN) { | ||||
| 		/* VSYNC interrupt, accept it */ | ||||
| 		decon->frame_start_cnt_cur++; | ||||
| 		wake_up_interruptible_all(&decon->wait_vstatus); | ||||
| 		if (decon->pdata->psr_mode == DECON_VIDEO_MODE) { | ||||
| 			decon->vsync_info.timestamp = timestamp; | ||||
| 			wake_up_interruptible_all(&decon->vsync_info.wait); | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	if (irq_sts_reg & INTERRUPT_FIFO_LEVEL_INT_EN) { | ||||
| 		decon->underrun_stat.fifo_level = fifo_level; | ||||
| 		decon->underrun_stat.prev_bw = decon->prev_bw; | ||||
| 		decon->underrun_stat.prev_int_bw = decon->prev_int_bw; | ||||
| 		decon->underrun_stat.prev_disp_bw = decon->prev_disp_bw; | ||||
| 		decon->underrun_stat.chmap = decon_read(0, RESOURCE_SEL_1); | ||||
| 		decon->underrun_stat.aclk = decon->res.pclk->rate; | ||||
| 		decon_f_get_enabled_win(decon); | ||||
| 		decon_oneshot_underrun_log(decon); | ||||
| 	} | ||||
| 
 | ||||
| 	if (irq_sts_reg & INTERRUPT_FRAME_DONE_INT_EN) { | ||||
| 		DISP_SS_EVENT_LOG(DISP_EVT_DECON_FRAMEDONE, &decon->sd, ktime_set(0, 0)); | ||||
| 		decon->frame_done_cnt_cur++; | ||||
| 		decon_lpd_trig_reset(decon); | ||||
| 		wake_up_interruptible_all(&decon->wait_frmdone); | ||||
| 		if (decon->sw_te_wa) { | ||||
| 			decon->vsync_info.timestamp = timestamp; | ||||
| 			wake_up_interruptible_all(&decon->vsync_info.wait); | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	if (irq_sts_reg & INTERRUPT_RESOURCE_CONFLICT_INT_EN) | ||||
| 		DISP_SS_EVENT_LOG(DISP_EVT_RSC_CONFLICT, &decon->sd, ktime_set(0, 0)); | ||||
| 
 | ||||
| irq_end: | ||||
| 	spin_unlock(&decon->slock); | ||||
| 
 | ||||
| 	return IRQ_HANDLED; | ||||
| } | ||||
| 
 | ||||
| int decon_f_get_clocks(struct decon_device *decon) | ||||
| { | ||||
| 	decon->res.dpll = clk_get(decon->dev, "disp_pll"); | ||||
| 	if (IS_ERR_OR_NULL(decon->res.dpll)) { | ||||
| 		decon_err("failed to get disp_pll\n"); | ||||
| 		return -ENODEV; | ||||
| 	} | ||||
| 
 | ||||
| 	decon->res.pclk = clk_get(decon->dev, "decon_pclk"); | ||||
| 	if (IS_ERR_OR_NULL(decon->res.pclk)) { | ||||
| 		decon_err("failed to get decon_pclk\n"); | ||||
| 		return -ENODEV; | ||||
| 	} | ||||
| 
 | ||||
| 	decon->res.eclk = clk_get(decon->dev, "eclk_user"); | ||||
| 	if (IS_ERR_OR_NULL(decon->res.eclk)) { | ||||
| 		decon_err("failed to get eclk_user\n"); | ||||
| 		return -ENODEV; | ||||
| 	} | ||||
| 
 | ||||
| 	decon->res.eclk_leaf = clk_get(decon->dev, "eclk_leaf"); | ||||
| 	if (IS_ERR_OR_NULL(decon->res.eclk_leaf)) { | ||||
| 		decon_err("failed to get eclk_leaf\n"); | ||||
| 		return -ENODEV; | ||||
| 	} | ||||
| 
 | ||||
| 	decon->res.vclk = clk_get(decon->dev, "vclk_user"); | ||||
| 	if (IS_ERR_OR_NULL(decon->res.vclk)) { | ||||
| 		decon_err("failed to get vclk_user\n"); | ||||
| 		return -ENODEV; | ||||
| 	} | ||||
| 
 | ||||
| 	decon->res.vclk_leaf = clk_get(decon->dev, "vclk_leaf"); | ||||
| 	if (IS_ERR_OR_NULL(decon->res.vclk_leaf)) { | ||||
| 		decon_err("failed to get vclk_leaf\n"); | ||||
| 		return -ENODEV; | ||||
| 	} | ||||
| 
 | ||||
| 	return 0; | ||||
| } | ||||
| 
 | ||||
| void decon_f_set_clocks(struct decon_device *decon) | ||||
| { | ||||
| 	struct device *dev = decon->dev; | ||||
| 	struct decon_clocks clks; | ||||
| 	struct decon_param p; | ||||
| 
 | ||||
| 	decon_to_init_param(decon, &p); | ||||
| 	decon_reg_get_clock_ratio(&clks, p.lcd_info); | ||||
| 
 | ||||
| 	/* VCLK */ | ||||
| 	decon_clk_set_rate(dev, decon->res.dpll, | ||||
| 			NULL, clks.decon[CLK_ID_DPLL] * MHZ); | ||||
| 	decon_clk_set_rate(dev, decon->res.vclk_leaf, | ||||
| 			NULL, clks.decon[CLK_ID_VCLK] * MHZ); | ||||
| 
 | ||||
| 	/* ECLK */ | ||||
| 	decon_clk_set_rate(dev, decon->res.eclk_leaf, | ||||
| 			NULL, clks.decon[CLK_ID_ECLK] * MHZ); | ||||
| 
 | ||||
| 	/* TODO: PCLK */ | ||||
| 	/* TODO: ACLK */ | ||||
| 	if (!IS_ENABLED(CONFIG_PM_DEVFREQ)) | ||||
| 		cal_dfs_set_rate(dvfs_disp, clks.decon[CLK_ID_ACLK] * 1000); | ||||
| 
 | ||||
| 	decon_dbg("%s:dpll %ld pclk %ld vclk %ld eclk %ld Mhz\n", | ||||
| 		__func__, | ||||
| 		clk_get_rate(decon->res.dpll) / MHZ, | ||||
| 		clk_get_rate(decon->res.pclk) / MHZ, | ||||
| 		clk_get_rate(decon->res.vclk_leaf) / MHZ, | ||||
| 		clk_get_rate(decon->res.eclk_leaf) / MHZ); | ||||
| 
 | ||||
| 	return; | ||||
| } | ||||
| 
 | ||||
| static void underrun_filter_handler(struct work_struct *work) | ||||
| { | ||||
| 	struct decon_device *decon = | ||||
| 			container_of(work, struct decon_device, fifo_irq_work); | ||||
| 	msleep(UNDERRUN_FILTER_INTERVAL_MS); | ||||
| 	decon->fifo_irq_status = UNDERRUN_FILTER_IDLE; | ||||
| } | ||||
| 
 | ||||
| int decon_f_register_irq(struct platform_device *pdev, struct decon_device *decon) | ||||
| { | ||||
| 	struct device *dev = decon->dev; | ||||
| 	struct resource *res; | ||||
| 	int ret = 0; | ||||
| 
 | ||||
| 	/* Get IRQ resource and register IRQ handler. */ | ||||
| 	/* 0: FIFO irq */ | ||||
| 	res = platform_get_resource(pdev, IORESOURCE_IRQ, 0); | ||||
| 	ret = devm_request_irq(dev, res->start, decon_f_irq_handler, 0, | ||||
| 			pdev->name, decon); | ||||
| 	if (ret) { | ||||
| 		decon_err("failed to install FIFO irq\n"); | ||||
| 		return ret; | ||||
| 	} | ||||
| 
 | ||||
| 	/* 1: VSTATUS INFO irq */ | ||||
| 	res = platform_get_resource(pdev, IORESOURCE_IRQ, 1); | ||||
| 	ret = devm_request_irq(dev, res->start, decon_f_irq_handler, | ||||
| 			0, pdev->name, decon); | ||||
| 	if (ret) { | ||||
| 		decon_err("failed to install VSTATUS irq\n"); | ||||
| 		return ret; | ||||
| 	} | ||||
| 
 | ||||
| 	if (decon->pdata->psr_mode == DECON_MIPI_COMMAND_MODE) { | ||||
| 		/* 2: I80 FrameDone irq */ | ||||
| 		res = platform_get_resource(pdev, IORESOURCE_IRQ, 2); | ||||
| 		ret = devm_request_irq(dev, res->start, decon_f_irq_handler, | ||||
| 				0, pdev->name, decon); | ||||
| 		if (ret) { | ||||
| 			decon_err("failed to install FrameDone irq\n"); | ||||
| 			return ret; | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	/* 3: Extra Interrupts: Resource Conflict irq */ | ||||
| 	res = platform_get_resource(pdev, IORESOURCE_IRQ, 3); | ||||
| 	ret = devm_request_irq(dev, res->start, decon_f_irq_handler, | ||||
| 			0, pdev->name, decon); | ||||
| 	if (ret) { | ||||
| 		decon_err("failed to install Extra irq\n"); | ||||
| 		return ret; | ||||
| 	} | ||||
| 
 | ||||
| 	if (decon->fifo_irq_status++ == UNDERRUN_FILTER_INIT) { | ||||
| 		decon->fifo_irq_wq = create_singlethread_workqueue("decon_fifo_irq_wq"); | ||||
| 		if (decon->fifo_irq_wq == NULL) { | ||||
| 			decon_err("%s:failed to create workqueue for fifo_irq_wq\n", __func__); | ||||
| 			return -ENOMEM; | ||||
| 		} | ||||
| 
 | ||||
| 		INIT_WORK(&decon->fifo_irq_work, underrun_filter_handler); | ||||
| 	} | ||||
| 
 | ||||
| 	return ret; | ||||
| } | ||||
							
								
								
									
										586
									
								
								drivers/video/fbdev/exynos/decon_8890/decon_helper.c
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										586
									
								
								drivers/video/fbdev/exynos/decon_8890/decon_helper.c
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,586 @@ | |||
| /*
 | ||||
|  * Copyright (c) 2014 Samsung Electronics Co., Ltd. | ||||
|  *		http://www.samsung.com
 | ||||
|  * | ||||
|  * Helper file for Samsung EXYNOS DECON driver | ||||
|  * | ||||
|  * 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. | ||||
| */ | ||||
| 
 | ||||
| #include <linux/clk.h> | ||||
| #include <linux/err.h> | ||||
| #include <linux/pm_runtime.h> | ||||
| #include <asm/cacheflush.h> | ||||
| #include <asm/page.h> | ||||
| 
 | ||||
| #include "decon.h" | ||||
| #include "dsim.h" | ||||
| #include "./vpp/vpp.h" | ||||
| #include "decon_helper.h" | ||||
| #include "./panels/lcd_ctrl.h" | ||||
| #include <video/mipi_display.h> | ||||
| 
 | ||||
| extern void *return_address(int); | ||||
| 
 | ||||
| int decon_clk_set_parent(struct device *dev, const char *child, const char *parent) | ||||
| { | ||||
| 	struct clk *p; | ||||
| 	struct clk *c; | ||||
| 
 | ||||
| 	p = clk_get(dev, parent); | ||||
| 	if (IS_ERR_OR_NULL(p)) { | ||||
| 		decon_err("%s: couldn't get clock : %s\n", __func__, parent); | ||||
| 		return -ENODEV; | ||||
| 	} | ||||
| 
 | ||||
| 	c = clk_get(dev, child); | ||||
| 	if (IS_ERR_OR_NULL(c)) { | ||||
| 		decon_err("%s: couldn't get clock : %s\n", __func__, child); | ||||
| 		return -ENODEV; | ||||
| 	} | ||||
| 
 | ||||
| 	clk_set_parent(c, p); | ||||
| 	clk_put(p); | ||||
| 	clk_put(c); | ||||
| 
 | ||||
| 	return 0; | ||||
| } | ||||
| 
 | ||||
| int decon_clk_set_rate(struct device *dev, struct clk *clk, | ||||
| 		const char *conid, unsigned long rate) | ||||
| { | ||||
| 	if (IS_ERR_OR_NULL(clk)) { | ||||
| 		if (IS_ERR_OR_NULL(conid)) { | ||||
| 			decon_err("%s: couldn't set clock(%ld)\n", __func__, rate); | ||||
| 			return -ENODEV; | ||||
| 		} | ||||
| 		clk = clk_get(dev, conid); | ||||
| 		clk_set_rate(clk, rate); | ||||
| 		clk_put(clk); | ||||
| 	} else { | ||||
| 		clk_set_rate(clk, rate); | ||||
| 	} | ||||
| 
 | ||||
| 	return 0; | ||||
| } | ||||
| 
 | ||||
| unsigned long decon_clk_get_rate(struct device *dev, const char *clkid) | ||||
| { | ||||
| 	struct clk *target; | ||||
| 	unsigned long rate; | ||||
| 
 | ||||
| 	target = clk_get(dev, clkid); | ||||
| 	if (IS_ERR_OR_NULL(target)) { | ||||
| 		decon_err("%s: couldn't get clock : %s\n", __func__, clkid); | ||||
| 		return -ENODEV; | ||||
| 	} | ||||
| 
 | ||||
| 	rate = clk_get_rate(target); | ||||
| 	clk_put(target); | ||||
| 
 | ||||
| 	return rate; | ||||
| } | ||||
| 
 | ||||
| void decon_to_psr_info(struct decon_device *decon, struct decon_mode_info *psr) | ||||
| { | ||||
| 	psr->psr_mode = decon->pdata->psr_mode; | ||||
| 	psr->trig_mode = decon->pdata->trig_mode; | ||||
| 	psr->dsi_mode = decon->pdata->dsi_mode; | ||||
| 	psr->out_type = decon->out_type; | ||||
| } | ||||
| 
 | ||||
| void decon_to_init_param(struct decon_device *decon, struct decon_param *p) | ||||
| { | ||||
| 	struct decon_lcd *lcd_info = decon->lcd_info; | ||||
| 	struct v4l2_mbus_framefmt mbus_fmt; | ||||
| 
 | ||||
| 	mbus_fmt.width = 0; | ||||
| 	mbus_fmt.height = 0; | ||||
| 	mbus_fmt.code = 0; | ||||
| 	mbus_fmt.field = 0; | ||||
| 	mbus_fmt.colorspace = 0; | ||||
| 
 | ||||
| 	p->lcd_info = lcd_info; | ||||
| 	p->psr.psr_mode = decon->pdata->psr_mode; | ||||
| 	p->psr.trig_mode = decon->pdata->trig_mode; | ||||
| 	p->psr.dsi_mode = decon->pdata->dsi_mode; | ||||
| 	p->psr.out_type = decon->out_type; | ||||
| 	p->nr_windows = decon->pdata->max_win; | ||||
| 	p->disp_ss_regs = decon->ss_regs; | ||||
| 	decon_dbg("###psr_mode %d trig_mode %d out_type %d nr_windows %d LCD[%d %d]\n", | ||||
| 		p->psr.psr_mode, p->psr.trig_mode, p->psr.out_type, p->nr_windows, | ||||
| 		decon->lcd_info->xres, decon->lcd_info->yres); | ||||
| } | ||||
| 
 | ||||
| /**
 | ||||
| * ----- APIs for DISPLAY_SUBSYSTEM_EVENT_LOG ----- | ||||
| */ | ||||
| /* ===== STATIC APIs ===== */ | ||||
| 
 | ||||
| #ifdef CONFIG_DECON_EVENT_LOG | ||||
| /* logging a event related with DECON */ | ||||
| static inline void disp_ss_event_log_decon | ||||
| 	(disp_ss_event_t type, struct v4l2_subdev *sd, ktime_t time) | ||||
| { | ||||
| 	struct decon_device *decon = container_of(sd, struct decon_device, sd); | ||||
| 	int idx = atomic_inc_return(&decon->disp_ss_log_idx) % DISP_EVENT_LOG_MAX; | ||||
| 	struct disp_ss_log *log = &decon->disp_ss_log[idx]; | ||||
| 
 | ||||
| 	if (time.tv64) | ||||
| 		log->time = time; | ||||
| 	else | ||||
| 		log->time = ktime_get(); | ||||
| 	log->type = type; | ||||
| 
 | ||||
| 	switch (type) { | ||||
| 	case DISP_EVT_DECON_SUSPEND: | ||||
| 	case DISP_EVT_DECON_RESUME: | ||||
| 	case DISP_EVT_ENTER_LPD: | ||||
| 	case DISP_EVT_EXIT_LPD: | ||||
| 		log->data.pm.pm_status = pm_runtime_active(decon->dev); | ||||
| 		log->data.pm.elapsed = ktime_sub(ktime_get(), log->time); | ||||
| 		break; | ||||
| 	case DISP_EVT_WB_SET_BUFFER: | ||||
| 	case DISP_EVT_WB_SW_TRIGGER: | ||||
| 		break; | ||||
| 	case DISP_EVT_TE_INTERRUPT: | ||||
| 	case DISP_EVT_UNDERRUN: | ||||
| 	case DISP_EVT_LINECNT_ZERO: | ||||
| 		break; | ||||
| 	default: | ||||
| 		/* Any remaining types will be log just time and type */ | ||||
| 		break; | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| /* logging a event related with DSIM */ | ||||
| static inline void disp_ss_event_log_dsim | ||||
| 	(disp_ss_event_t type, struct v4l2_subdev *sd, ktime_t time) | ||||
| { | ||||
| 	struct dsim_device *dsim = container_of(sd, struct dsim_device, sd); | ||||
| 	struct decon_device *decon = get_decon_drvdata(dsim->id); | ||||
| 	int idx = atomic_inc_return(&decon->disp_ss_log_idx) % DISP_EVENT_LOG_MAX; | ||||
| 	struct disp_ss_log *log = &decon->disp_ss_log[idx]; | ||||
| 
 | ||||
| 	if (time.tv64) | ||||
| 		log->time = time; | ||||
| 	else | ||||
| 		log->time = ktime_get(); | ||||
| 	log->type = type; | ||||
| 
 | ||||
| 	switch (type) { | ||||
| 	case DISP_EVT_DSIM_SUSPEND: | ||||
| 	case DISP_EVT_DSIM_RESUME: | ||||
| 	case DISP_EVT_ENTER_ULPS: | ||||
| 	case DISP_EVT_EXIT_ULPS: | ||||
| 		log->data.pm.pm_status = pm_runtime_active(dsim->dev); | ||||
| 		log->data.pm.elapsed = ktime_sub(ktime_get(), log->time); | ||||
| 		break; | ||||
| 	default: | ||||
| 		/* Any remaining types will be log just time and type */ | ||||
| 		break; | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| /* get decon's id used by vpp */ | ||||
| static int __get_decon_id_for_vpp(struct v4l2_subdev *sd) | ||||
| { | ||||
| 	struct decon_device *decon; | ||||
| 	struct vpp_dev *vpp = v4l2_get_subdevdata(sd); | ||||
| 	int idx; | ||||
| 	int ret = 0; | ||||
| 
 | ||||
| 	for (idx = 0; idx < NUM_DECON_IPS; idx++) { | ||||
| 		decon = get_decon_drvdata(idx); | ||||
| 		if (!decon || IS_ERR_OR_NULL(decon->debug_event)) | ||||
| 			continue; | ||||
| 		if (decon->vpp_used[vpp->id] == true) | ||||
| 			ret = decon->id; | ||||
| 	} | ||||
| 
 | ||||
| 	return ret; | ||||
| } | ||||
| 
 | ||||
| /* logging a event related with VPP */ | ||||
| static inline void disp_ss_event_log_vpp | ||||
| 	(disp_ss_event_t type, struct v4l2_subdev *sd, ktime_t time) | ||||
| { | ||||
| 	struct decon_device *decon = get_decon_drvdata(__get_decon_id_for_vpp(sd)); | ||||
| 	int idx = atomic_inc_return(&decon->disp_ss_log_idx) % DISP_EVENT_LOG_MAX; | ||||
| 	struct disp_ss_log *log = &decon->disp_ss_log[idx]; | ||||
| 	struct vpp_dev *vpp = v4l2_get_subdevdata(sd); | ||||
| 
 | ||||
| 	if (time.tv64) | ||||
| 		log->time = time; | ||||
| 	else | ||||
| 		log->time = ktime_get(); | ||||
| 	log->type = type; | ||||
| 
 | ||||
| 	switch (type) { | ||||
| 	case DISP_EVT_VPP_SUSPEND: | ||||
| 	case DISP_EVT_VPP_RESUME: | ||||
| 		log->data.pm.pm_status = pm_runtime_active(&vpp->pdev->dev); | ||||
| 		log->data.pm.elapsed = ktime_sub(ktime_get(), log->time); | ||||
| 		break; | ||||
| 	case DISP_EVT_VPP_FRAMEDONE: | ||||
| 	case DISP_EVT_VPP_STOP: | ||||
| 	case DISP_EVT_VPP_WINCON: | ||||
| 		log->data.vpp.id = vpp->id; | ||||
| 		log->data.vpp.start_cnt = vpp->start_count; | ||||
| 		log->data.vpp.done_cnt = vpp->done_count; | ||||
| 		break; | ||||
| 	default: | ||||
| 		log->data.vpp.id = vpp->id; | ||||
| 		break; | ||||
| 	} | ||||
| 
 | ||||
| 	return; | ||||
| } | ||||
| 
 | ||||
| /* If event are happend continuously, then ignore */ | ||||
| static bool disp_ss_event_ignore | ||||
| 	(disp_ss_event_t type, struct decon_device *decon) | ||||
| { | ||||
| 	int latest = atomic_read(&decon->disp_ss_log_idx) % DISP_EVENT_LOG_MAX; | ||||
| 	struct disp_ss_log *log; | ||||
| 	int idx; | ||||
| 
 | ||||
| 	/* Seek a oldest from current index */ | ||||
| 	idx = (latest + DISP_EVENT_LOG_MAX - DECON_ENTER_LPD_CNT) % DISP_EVENT_LOG_MAX; | ||||
| 	do { | ||||
| 		if (++idx >= DISP_EVENT_LOG_MAX) | ||||
| 			idx = 0; | ||||
| 
 | ||||
| 		log = &decon->disp_ss_log[idx]; | ||||
| 		if (log->type != type) | ||||
| 			return false; | ||||
| 	} while (latest != idx); | ||||
| 
 | ||||
| 	return true; | ||||
| } | ||||
| 
 | ||||
| /* ===== EXTERN APIs ===== */ | ||||
| /* Common API to log a event related with DECON/DSIM/VPP */ | ||||
| void DISP_SS_EVENT_LOG(disp_ss_event_t type, struct v4l2_subdev *sd, ktime_t time) | ||||
| { | ||||
| 	struct decon_device *decon = get_decon_drvdata(0); | ||||
| 
 | ||||
| 	if (!decon || IS_ERR_OR_NULL(decon->debug_event)) | ||||
| 		return; | ||||
| 
 | ||||
| 	/* log a eventy softly */ | ||||
| 	switch (type) { | ||||
| 	case DISP_EVT_TE_INTERRUPT: | ||||
| 	case DISP_EVT_UNDERRUN: | ||||
| 		/* If occurs continuously, skipped. It is a burden */ | ||||
| 		if (disp_ss_event_ignore(type, decon)) | ||||
| 			break; | ||||
| 	case DISP_EVT_BLANK: | ||||
| 	case DISP_EVT_UNBLANK: | ||||
| 	case DISP_EVT_ENTER_LPD: | ||||
| 	case DISP_EVT_EXIT_LPD: | ||||
| 	case DISP_EVT_DECON_SUSPEND: | ||||
| 	case DISP_EVT_DECON_RESUME: | ||||
| 	case DISP_EVT_LINECNT_ZERO: | ||||
| 	case DISP_EVT_TRIG_MASK: | ||||
| 	case DISP_EVT_TRIG_UNMASK: | ||||
| 	case DISP_EVT_DECON_FRAMEDONE: | ||||
| 	case DISP_EVT_DECON_FRAMEDONE_WAIT: | ||||
| 	case DISP_EVT_WB_SET_BUFFER: | ||||
| 	case DISP_EVT_WB_SW_TRIGGER: | ||||
| 	case DISP_EVT_DECON_SHUTDOWN: | ||||
| 	case DISP_EVT_RSC_CONFLICT: | ||||
| 		disp_ss_event_log_decon(type, sd, time); | ||||
| 		break; | ||||
| 	case DISP_EVT_DSIM_FRAMEDONE: | ||||
| 	case DISP_EVT_ENTER_ULPS: | ||||
| 	case DISP_EVT_EXIT_ULPS: | ||||
| 	case DISP_EVT_DSIM_SHUTDOWN: | ||||
| 		disp_ss_event_log_dsim(type, sd, time); | ||||
| 		break; | ||||
| 	case DISP_EVT_VPP_FRAMEDONE: | ||||
| 	case DISP_EVT_VPP_STOP: | ||||
| 	case DISP_EVT_VPP_WINCON: | ||||
| 		disp_ss_event_log_vpp(type, sd, time); | ||||
| 		break; | ||||
| 	default: | ||||
| 		break; | ||||
| 	} | ||||
| 
 | ||||
| 	if (decon->disp_ss_log_level == DISP_EVENT_LEVEL_LOW) | ||||
| 		return; | ||||
| 
 | ||||
| 	/* additionally logging hardly */ | ||||
| 	switch (type) { | ||||
| 	case DISP_EVT_ACT_VSYNC: | ||||
| 	case DISP_EVT_DEACT_VSYNC: | ||||
| 	case DISP_EVT_WIN_CONFIG: | ||||
| 		disp_ss_event_log_decon(type, sd, time); | ||||
| 		break; | ||||
| 	case DISP_EVT_DSIM_SUSPEND: | ||||
| 	case DISP_EVT_DSIM_RESUME: | ||||
| 		disp_ss_event_log_dsim(type, sd, time); | ||||
| 		break; | ||||
| 	case DISP_EVT_VPP_SUSPEND: | ||||
| 	case DISP_EVT_VPP_RESUME: | ||||
| 	case DISP_EVT_VPP_UPDATE_DONE: | ||||
| 	case DISP_EVT_VPP_SHADOW_UPDATE: | ||||
| 		disp_ss_event_log_vpp(type, sd, time); | ||||
| 	default: | ||||
| 		break; | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| void DISP_SS_EVENT_LOG_WINCON(struct v4l2_subdev *sd, struct decon_reg_data *regs) | ||||
| { | ||||
| 	struct decon_device *decon = container_of(sd, struct decon_device, sd); | ||||
| 	int idx = atomic_inc_return(&decon->disp_ss_log_idx) % DISP_EVENT_LOG_MAX; | ||||
| 	struct disp_ss_log *log = &decon->disp_ss_log[idx]; | ||||
| 	int win = 0; | ||||
| 	bool window_updated = false; | ||||
| 
 | ||||
| 	log->time = ktime_get(); | ||||
| 	log->type = DISP_EVT_UPDATE_HANDLER; | ||||
| 
 | ||||
| 	for (win = 0; win < MAX_DECON_WIN; win++) { | ||||
| 		if (regs->win_regs[win].wincon & WIN_CONTROL_EN_F) { | ||||
| 			memcpy(&log->data.reg.win_regs[win], ®s->win_regs[win], | ||||
| 				sizeof(struct decon_window_regs)); | ||||
| 			memcpy(&log->data.reg.win_config[win], ®s->vpp_config[win], | ||||
| 				sizeof(struct decon_win_config)); | ||||
| 		} else { | ||||
| 			log->data.reg.win_config[win].state = DECON_WIN_STATE_DISABLED; | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	if (decon->out_type == DECON_OUT_WB) | ||||
| 		memcpy(&log->data.reg.win_config[MAX_DECON_WIN], ®s->vpp_config[MAX_DECON_WIN], | ||||
| 				sizeof(struct decon_win_config)); | ||||
| 
 | ||||
| #ifdef CONFIG_FB_WINDOW_UPDATE | ||||
| 	if ((regs->need_update) || | ||||
| 		(decon->need_update && regs->update_win.w)) { | ||||
| 		window_updated = true; | ||||
| 		memcpy(&log->data.reg.win, ®s->update_win, | ||||
| 				sizeof(struct decon_rect)); | ||||
| 	} | ||||
| #endif | ||||
| 	if (!window_updated) { | ||||
| 		log->data.reg.win.x = 0; | ||||
| 		log->data.reg.win.y = 0; | ||||
| 		log->data.reg.win.w = decon->lcd_info->xres; | ||||
| 		log->data.reg.win.h = decon->lcd_info->yres; | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| /* Common API to log a event related with DSIM COMMAND */ | ||||
| void DISP_SS_EVENT_LOG_CMD(struct v4l2_subdev *sd, u32 cmd_id, unsigned long data) | ||||
| { | ||||
| 	struct dsim_device *dsim = container_of(sd, struct dsim_device, sd); | ||||
| 	struct decon_device *decon = get_decon_drvdata(dsim->id); | ||||
| 	int idx, i; | ||||
| 	struct disp_ss_log *log; | ||||
| 
 | ||||
| 	if (!decon || IS_ERR_OR_NULL(decon->debug_event)) | ||||
| 		return; | ||||
| 
 | ||||
| 	idx = atomic_inc_return(&decon->disp_ss_log_idx) % DISP_EVENT_LOG_MAX; | ||||
| 	log = &decon->disp_ss_log[idx]; | ||||
| 
 | ||||
| 	log->time = ktime_get(); | ||||
| 	log->type = DISP_EVT_DSIM_COMMAND; | ||||
| 	log->data.cmd_buf.id = cmd_id; | ||||
| 	if (cmd_id == MIPI_DSI_DCS_LONG_WRITE) | ||||
| 		log->data.cmd_buf.buf = *(u8 *)(data); | ||||
| 	else | ||||
| 		log->data.cmd_buf.buf = (u8)data; | ||||
| 
 | ||||
| 	for (i = 0; i < DISP_CALLSTACK_MAX; i++) | ||||
| 		log->data.cmd_buf.caller[i] = (void *)((size_t)return_address(i + 1)); | ||||
| } | ||||
| 
 | ||||
| /* display logged events related with DECON */ | ||||
| void DISP_SS_EVENT_SHOW(struct seq_file *s, struct decon_device *decon) | ||||
| { | ||||
| 	int idx = atomic_read(&decon->disp_ss_log_idx) % DISP_EVENT_LOG_MAX; | ||||
| 	struct disp_ss_log *log; | ||||
| 	int latest = idx; | ||||
| 	struct timeval tv; | ||||
| 	ktime_t prev_ktime; | ||||
| 
 | ||||
| 	/* TITLE */ | ||||
| 	seq_printf(s, "-------------------DECON%d EVENT LOGGER ----------------------\n", | ||||
| 			decon->id); | ||||
| 	seq_printf(s, "-- STATUS: LPD(%s) ", IS_ENABLED(CONFIG_DECON_LPD_DISPLAY) ? "on" : "off"); | ||||
| 	seq_printf(s, "PKTGO(%s) ", IS_ENABLED(CONFIG_DECON_MIPI_DSI_PKTGO) ? "on" : "off"); | ||||
| 	seq_printf(s, "BlockMode(%s) ", IS_ENABLED(CONFIG_DECON_BLOCKING_MODE) ? "on" : "off"); | ||||
| 	seq_printf(s, "Window_Update(%s)\n", IS_ENABLED(CONFIG_FB_WINDOW_UPDATE) ? "on" : "off"); | ||||
| 	seq_puts(s, "-------------------------------------------------------------\n"); | ||||
| 	seq_printf(s, "%14s  %20s  %20s\n", | ||||
| 		"Time", "Event ID", "Remarks"); | ||||
| 	seq_puts(s, "-------------------------------------------------------------\n"); | ||||
| 
 | ||||
| 	/* return if there is no event log */ | ||||
| 	if (idx < 0) | ||||
| 		return; | ||||
| 	/* Seek a oldest from current index */ | ||||
| 	idx = (idx + DISP_EVENT_LOG_MAX - DISP_EVENT_PRINT_MAX) % DISP_EVENT_LOG_MAX; | ||||
| 	prev_ktime = ktime_set(0, 0); | ||||
| 
 | ||||
| 	do { | ||||
| 		if (++idx >= DISP_EVENT_LOG_MAX) | ||||
| 			idx = 0; | ||||
| 
 | ||||
| 		/* Seek a index */ | ||||
| 		log = &decon->disp_ss_log[idx]; | ||||
| 
 | ||||
| 		/* TIME */ | ||||
| 		tv = ktime_to_timeval(log->time); | ||||
| 		seq_printf(s, "[%6ld.%06ld] ", tv.tv_sec, tv.tv_usec); | ||||
| 
 | ||||
| 		/* If there is no timestamp, then exit directly */ | ||||
| 		if (!tv.tv_sec) | ||||
| 			break; | ||||
| 
 | ||||
| 		/* EVETN ID + Information */ | ||||
| 		switch (log->type) { | ||||
| 		case DISP_EVT_BLANK: | ||||
| 			seq_printf(s, "%20s  %20s", "FB_BLANK", "-\n"); | ||||
| 			break; | ||||
| 		case DISP_EVT_UNBLANK: | ||||
| 			seq_printf(s, "%20s  %20s", "FB_UNBLANK", "-\n"); | ||||
| 			break; | ||||
| 		case DISP_EVT_ACT_VSYNC: | ||||
| 			seq_printf(s, "%20s  %20s", "ACT_VSYNC", "-\n"); | ||||
| 			break; | ||||
| 		case DISP_EVT_DEACT_VSYNC: | ||||
| 			seq_printf(s, "%20s  %20s", "DEACT_VSYNC", "-\n"); | ||||
| 			break; | ||||
| 		case DISP_EVT_WIN_CONFIG: | ||||
| 			seq_printf(s, "%20s  %20s", "WIN_CONFIG", "-\n"); | ||||
| 			break; | ||||
| 		case DISP_EVT_TE_INTERRUPT: | ||||
| 			prev_ktime = ktime_sub(log->time, prev_ktime); | ||||
| 			seq_printf(s, "%20s  ", "TE_INTERRUPT"); | ||||
| 			seq_printf(s, "time_diff=[%ld.%04lds]\n", | ||||
| 					ktime_to_timeval(prev_ktime).tv_sec, | ||||
| 					ktime_to_timeval(prev_ktime).tv_usec/100); | ||||
| 			/* Update for latest DISP_EVT_TE time */ | ||||
| 			prev_ktime = log->time; | ||||
| 			break; | ||||
| 		case DISP_EVT_UNDERRUN: | ||||
| 			seq_printf(s, "%20s  %20s", "UNDER_RUN", "-\n"); | ||||
| 			break; | ||||
| 		case DISP_EVT_DECON_FRAMEDONE: | ||||
| 			seq_printf(s, "%20s  %20s", "DECON_FRAME_DONE", "-\n"); | ||||
| 			break; | ||||
| 		case DISP_EVT_UPDATE_HANDLER: | ||||
| 			seq_printf(s, "%20s  ", "UPDATE_HANDLER"); | ||||
| 			seq_printf(s, "Partial Size (%d,%d,%d,%d)\n", | ||||
| 					log->data.reg.win.x, | ||||
| 					log->data.reg.win.y, | ||||
| 					log->data.reg.win.w, | ||||
| 					log->data.reg.win.h); | ||||
| 			break; | ||||
| 		case DISP_EVT_DSIM_COMMAND: | ||||
| 			seq_printf(s, "%20s  ", "DSIM_COMMAND"); | ||||
| 			seq_printf(s, "id=0x%x, command=0x%x\n", | ||||
| 					log->data.cmd_buf.id, | ||||
| 					log->data.cmd_buf.buf); | ||||
| 			break; | ||||
| 		case DISP_EVT_TRIG_MASK: | ||||
| 			seq_printf(s, "%20s  %20s", "TRIG_MASK", "-\n"); | ||||
| 			break; | ||||
| 		case DISP_EVT_TRIG_UNMASK: | ||||
| 			seq_printf(s, "%20s  %20s", "TRIG_UNMASK", "-\n"); | ||||
| 			break; | ||||
| 		case DISP_EVT_VPP_WINCON: | ||||
| 			seq_printf(s, "%20s  ", "VPP_WINCON"); | ||||
| 			seq_printf(s, "ID:%d, start= %d, done= %d\n", | ||||
| 					log->data.vpp.id, | ||||
| 					log->data.vpp.start_cnt, | ||||
| 					log->data.vpp.done_cnt); | ||||
| 			break; | ||||
| 		case DISP_EVT_VPP_FRAMEDONE: | ||||
| 			seq_printf(s, "%20s  ", "VPP_FRAMEDONE"); | ||||
| 			seq_printf(s, "ID:%d, start=%d, done=%d\n", | ||||
| 					log->data.vpp.id, | ||||
| 					log->data.vpp.start_cnt, | ||||
| 					log->data.vpp.done_cnt); | ||||
| 			break; | ||||
| 		case DISP_EVT_VPP_STOP: | ||||
| 			seq_printf(s, "%20s  ", "VPP_STOP"); | ||||
| 			seq_printf(s, "(id:%d)\n", log->data.vpp.id); | ||||
| 			break; | ||||
| 		case DISP_EVT_VPP_SUSPEND: | ||||
| 			seq_printf(s, "%20s  %20s", "VPP_SUSPEND", "-\n"); | ||||
| 			break; | ||||
| 		case DISP_EVT_VPP_RESUME: | ||||
| 			seq_printf(s, "%20s  %20s", "VPP_RESUME", "-\n"); | ||||
| 			break; | ||||
| 		case DISP_EVT_DECON_SUSPEND: | ||||
| 			seq_printf(s, "%20s  %20s", "DECON_SUSPEND", "-\n"); | ||||
| 			break; | ||||
| 		case DISP_EVT_DECON_RESUME: | ||||
| 			seq_printf(s, "%20s  %20s", "DECON_RESUME", "-\n"); | ||||
| 			break; | ||||
| 		case DISP_EVT_ENTER_LPD: | ||||
| 			seq_printf(s, "%20s  ", "ENTER_LPD"); | ||||
| 			tv = ktime_to_timeval(log->data.pm.elapsed); | ||||
| 			seq_printf(s, "pm=%s, elapsed=[%ld.%03lds]\n", | ||||
| 					log->data.pm.pm_status ? "active " : "suspend", | ||||
| 					tv.tv_sec, tv.tv_usec/1000); | ||||
| 			break; | ||||
| 		case DISP_EVT_EXIT_LPD: | ||||
| 			seq_printf(s, "%20s  ", "EXIT_LPD"); | ||||
| 			tv = ktime_to_timeval(log->data.pm.elapsed); | ||||
| 			seq_printf(s, "pm=%s, elapsed=[%ld.%03lds]\n", | ||||
| 					log->data.pm.pm_status ? "active " : "suspend", | ||||
| 					tv.tv_sec, tv.tv_usec/1000); | ||||
| 			break; | ||||
| 		case DISP_EVT_DSIM_SUSPEND: | ||||
| 			seq_printf(s, "%20s  %20s", "DSIM_SUSPEND", "-\n"); | ||||
| 			break; | ||||
| 		case DISP_EVT_DSIM_RESUME: | ||||
| 			seq_printf(s, "%20s  %20s", "DSIM_RESUME", "-\n"); | ||||
| 			break; | ||||
| 		case DISP_EVT_ENTER_ULPS: | ||||
| 			seq_printf(s, "%20s  ", "ENTER_ULPS"); | ||||
| 			tv = ktime_to_timeval(log->data.pm.elapsed); | ||||
| 			seq_printf(s, "pm=%s, elapsed=[%ld.%03lds]\n", | ||||
| 					log->data.pm.pm_status ? "active " : "suspend", | ||||
| 					tv.tv_sec, tv.tv_usec/1000); | ||||
| 			break; | ||||
| 		case DISP_EVT_EXIT_ULPS: | ||||
| 			seq_printf(s, "%20s  ", "EXIT_ULPS"); | ||||
| 			tv = ktime_to_timeval(log->data.pm.elapsed); | ||||
| 			seq_printf(s, "pm=%s, elapsed=[%ld.%03lds]\n", | ||||
| 					log->data.pm.pm_status ? "active " : "suspend", | ||||
| 					tv.tv_sec, tv.tv_usec/1000); | ||||
| 			break; | ||||
| 		default: | ||||
| 			seq_printf(s, "%20s  (%2d)\n", "NO_DEFINED", log->type); | ||||
| 			break; | ||||
| 		} | ||||
| 	} while (latest != idx); | ||||
| 
 | ||||
| 	seq_puts(s, "-------------------------------------------------------------\n"); | ||||
| 
 | ||||
| 	return; | ||||
| } | ||||
| 
 | ||||
| void DISP_SS_EVENT_SIZE_ERR_LOG(struct v4l2_subdev *sd, struct disp_ss_size_info *info) | ||||
| { | ||||
| 	struct decon_device *decon = container_of(sd, struct decon_device, sd); | ||||
| 	int idx = (decon->disp_ss_size_log_idx++) % DISP_EVENT_SIZE_ERR_MAX; | ||||
| 	struct disp_ss_size_err_info *log = &decon->disp_ss_size_log[idx]; | ||||
| 
 | ||||
| 	if (!decon) | ||||
| 		return; | ||||
| 
 | ||||
| 	log->time = ktime_get(); | ||||
| 	memcpy(&log->info, info, sizeof(struct disp_ss_size_info)); | ||||
| } | ||||
| #endif | ||||
							
								
								
									
										26
									
								
								drivers/video/fbdev/exynos/decon_8890/decon_helper.h
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										26
									
								
								drivers/video/fbdev/exynos/decon_8890/decon_helper.h
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,26 @@ | |||
| /*
 | ||||
|  * Copyright (c) 2014 Samsung Electronics Co., Ltd. | ||||
|  *		http://www.samsung.com
 | ||||
|  * | ||||
|  * Header file for Exynos DECON driver | ||||
|  * | ||||
|  * 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. | ||||
| */ | ||||
| 
 | ||||
| #ifndef __SAMSUNG_DECON_HELPER_H__ | ||||
| #define __SAMSUNG_DECON_HELPER_H__ | ||||
| 
 | ||||
| #include <linux/device.h> | ||||
| 
 | ||||
| #include "decon.h" | ||||
| 
 | ||||
| int decon_clk_set_parent(struct device *dev, const char *c, const char *p); | ||||
| int decon_clk_set_rate(struct device *dev, struct clk *clk, | ||||
| 		const char *conid, unsigned long rate); | ||||
| unsigned long decon_clk_get_rate(struct device *dev, const char *clkid); | ||||
| void decon_to_psr_info(struct decon_device *decon, struct decon_mode_info *psr); | ||||
| void decon_to_init_param(struct decon_device *decon, struct decon_param *p); | ||||
| 
 | ||||
| #endif /* __SAMSUNG_DECON_HELPER_H__ */ | ||||
							
								
								
									
										1343
									
								
								drivers/video/fbdev/exynos/decon_8890/decon_reg_8890.c
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										1343
									
								
								drivers/video/fbdev/exynos/decon_8890/decon_reg_8890.c
									
										
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load diff
											
										
									
								
							
							
								
								
									
										107
									
								
								drivers/video/fbdev/exynos/decon_8890/decon_s.c
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										107
									
								
								drivers/video/fbdev/exynos/decon_8890/decon_s.c
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,107 @@ | |||
| /*
 | ||||
|  * Copyright (c) 2014 Samsung Electronics Co., Ltd. | ||||
|  *		http://www.samsung.com
 | ||||
|  * | ||||
|  * Core file for Samsung EXYNOS DECON driver | ||||
|  * | ||||
|  * 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. | ||||
| */ | ||||
| 
 | ||||
| #include <linux/of_gpio.h> | ||||
| #include <linux/clk-provider.h> | ||||
| 
 | ||||
| #include "decon.h" | ||||
| #include "decon_helper.h" | ||||
| 
 | ||||
| irqreturn_t decon_s_irq_handler(int irq, void *dev_data) | ||||
| { | ||||
| 	struct decon_device *decon = dev_data; | ||||
| 	ktime_t timestamp = ktime_get(); | ||||
| 	u32 irq_sts_reg; | ||||
| 
 | ||||
| 	spin_lock(&decon->slock); | ||||
| 	if ((decon->state == DECON_STATE_OFF) || | ||||
| 		(decon->state == DECON_STATE_LPD)) { | ||||
| 		goto irq_end; | ||||
| 	} | ||||
| 
 | ||||
| 	irq_sts_reg = decon_reg_get_interrupt_and_clear(decon->id); | ||||
| 	if (irq_sts_reg & INTERRUPT_DISPIF_VSTATUS_INT_EN) { | ||||
| 		decon->vsync_info.timestamp = timestamp; | ||||
| 		wake_up_interruptible_all(&decon->vsync_info.wait); | ||||
| 	} | ||||
| 	if (irq_sts_reg & INTERRUPT_FIFO_LEVEL_INT_EN) { | ||||
| 		DISP_SS_EVENT_LOG(DISP_EVT_UNDERRUN, &decon->sd, ktime_set(0, 0)); | ||||
| 		decon_err("DECON-ext FIFO underrun\n"); | ||||
| 	} | ||||
| 	if (irq_sts_reg & INTERRUPT_FRAME_DONE_INT_EN) { | ||||
| 		DISP_SS_EVENT_LOG(DISP_EVT_DECON_FRAMEDONE, &decon->sd, ktime_set(0, 0)); | ||||
| 		decon_warn("DECON-ext frame done interrupt shouldn't happen\n"); | ||||
| 		decon->frame_done_cnt_cur++; | ||||
| 		decon_lpd_trig_reset(decon); | ||||
| 	} | ||||
| 	if (irq_sts_reg & INTERRUPT_RESOURCE_CONFLICT_INT_EN) | ||||
| 		DISP_SS_EVENT_LOG(DISP_EVT_RSC_CONFLICT, &decon->sd, | ||||
| 				ktime_set(0, 0)); | ||||
| 
 | ||||
| irq_end: | ||||
| 	spin_unlock(&decon->slock); | ||||
| 	return IRQ_HANDLED; | ||||
| } | ||||
| 
 | ||||
| int decon_s_get_clocks(struct decon_device *decon) | ||||
| { | ||||
| 	return 0; | ||||
| } | ||||
| 
 | ||||
| void decon_s_set_clocks(struct decon_device *decon) | ||||
| { | ||||
| } | ||||
| 
 | ||||
| int decon_s_register_irq(struct platform_device *pdev, struct decon_device *decon) | ||||
| { | ||||
| 	struct device *dev = decon->dev; | ||||
| 	struct resource *res; | ||||
| 	int ret = 0; | ||||
| 
 | ||||
| 	/* Get IRQ resource and register IRQ handler. */ | ||||
| 	/* 0: FIFO irq */ | ||||
| 	res = platform_get_resource(pdev, IORESOURCE_IRQ, 0); | ||||
| 	ret = devm_request_irq(dev, res->start, decon_s_irq_handler, 0, | ||||
| 			pdev->name, decon); | ||||
| 	if (ret) { | ||||
| 		decon_err("failed to install irq\n"); | ||||
| 		return ret; | ||||
| 	} | ||||
| 
 | ||||
| 	/* 1: VStatus irq */ | ||||
| 	res = platform_get_resource(pdev, IORESOURCE_IRQ, 1); | ||||
| 	ret = devm_request_irq(dev, res->start, decon_s_irq_handler, 0, | ||||
| 			pdev->name, decon); | ||||
| 	if (ret) { | ||||
| 		decon_err("failed to install irq\n"); | ||||
| 		return ret; | ||||
| 	} | ||||
| 
 | ||||
| 	/* 2: FrameDone irq */ | ||||
| 	res = platform_get_resource(pdev, IORESOURCE_IRQ, 2); | ||||
| 	ret = devm_request_irq(dev, res->start, decon_s_irq_handler, 0, | ||||
| 			pdev->name, decon); | ||||
| 	if (ret) { | ||||
| 		decon_err("failed to install irq\n"); | ||||
| 		return ret; | ||||
| 	} | ||||
| 
 | ||||
| 	/* 3: Extra Interrupts: Resource Conflict irq */ | ||||
| 	res = platform_get_resource(pdev, IORESOURCE_IRQ, 3); | ||||
| 	ret = devm_request_irq(dev, res->start, decon_s_irq_handler, 0, | ||||
| 			pdev->name, decon); | ||||
| 	if (ret) { | ||||
| 		decon_err("failed to install irq\n"); | ||||
| 		return ret; | ||||
| 	} | ||||
| 
 | ||||
| 	return ret; | ||||
| } | ||||
							
								
								
									
										170
									
								
								drivers/video/fbdev/exynos/decon_8890/decon_t.c
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										170
									
								
								drivers/video/fbdev/exynos/decon_8890/decon_t.c
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,170 @@ | |||
| /*
 | ||||
|  * Copyright (c) 2015 Samsung Electronics Co., Ltd. | ||||
|  *		http://www.samsung.com
 | ||||
|  * | ||||
|  * Core file for Samsung EXYNOS DECON driver | ||||
|  * | ||||
|  * 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. | ||||
| */ | ||||
| 
 | ||||
| #include <linux/of_gpio.h> | ||||
| #include <linux/clk-provider.h> | ||||
| 
 | ||||
| #include "decon.h" | ||||
| #include "decon_helper.h" | ||||
| #include "../../../../staging/android/sw_sync.h" | ||||
| 
 | ||||
| int decon_t_set_lcd_info(struct decon_device *decon) | ||||
| { | ||||
| 	struct decon_lcd *lcd_info; | ||||
| 
 | ||||
| 	if (decon->lcd_info != NULL) | ||||
| 		return 0; | ||||
| 
 | ||||
| 	lcd_info = kzalloc(sizeof(struct decon_lcd), GFP_KERNEL); | ||||
| 	if (!lcd_info) { | ||||
| 		decon_err("could not allocate decon_lcd for wb\n"); | ||||
| 		return -ENOMEM; | ||||
| 	} | ||||
| 
 | ||||
| 	decon->lcd_info = lcd_info; | ||||
| 	decon->lcd_info->width = 1920; | ||||
| 	decon->lcd_info->height = 1080; | ||||
| 	decon->lcd_info->xres = 1920; | ||||
| 	decon->lcd_info->yres = 1080; | ||||
| 	decon->lcd_info->vfp = 2; | ||||
| 	decon->lcd_info->vbp = 20; | ||||
| 	decon->lcd_info->hfp = 20; | ||||
| 	decon->lcd_info->hbp = 20; | ||||
| 	decon->lcd_info->vsa = 2; | ||||
| 	decon->lcd_info->hsa = 20; | ||||
| 	decon->lcd_info->fps = 60; | ||||
| 	decon->out_type = DECON_OUT_WB; | ||||
| 
 | ||||
| 	decon_info("decon_%d output size for writeback %dx%d\n", decon->id, | ||||
| 			decon->lcd_info->width, decon->lcd_info->height); | ||||
| 
 | ||||
| 	return 0; | ||||
| } | ||||
| 
 | ||||
| irqreturn_t decon_t_irq_handler(int irq, void *dev_data) | ||||
| { | ||||
| 	struct decon_device *decon = dev_data; | ||||
| 	u32 irq_sts_reg; | ||||
| 
 | ||||
| 	spin_lock(&decon->slock); | ||||
| 	if ((decon->state == DECON_STATE_OFF) || | ||||
| 		(decon->state == DECON_STATE_LPD)) { | ||||
| 		goto irq_end; | ||||
| 	} | ||||
| 
 | ||||
| 	irq_sts_reg = decon_reg_get_interrupt_and_clear(decon->id); | ||||
| 
 | ||||
| 	if (irq_sts_reg & INTERRUPT_FIFO_LEVEL_INT_EN) { | ||||
| 		DISP_SS_EVENT_LOG(DISP_EVT_UNDERRUN, &decon->sd, ktime_set(0, 0)); | ||||
| 		decon_err("DECON_T FIFO underrun\n"); | ||||
| 	} | ||||
| 	if (irq_sts_reg & INTERRUPT_FRAME_DONE_INT_EN) { | ||||
| 		decon_lpd_trig_reset(decon); | ||||
| 		DISP_SS_EVENT_LOG(DISP_EVT_DECON_FRAMEDONE, &decon->sd, ktime_set(0, 0)); | ||||
| 		decon_dbg("%s Frame Done is occured. timeline:%d, %d\n", | ||||
| 				__func__, decon->timeline->value, decon->timeline_max); | ||||
| 	} | ||||
| 	if (irq_sts_reg & INTERRUPT_RESOURCE_CONFLICT_INT_EN) | ||||
| 		DISP_SS_EVENT_LOG(DISP_EVT_RSC_CONFLICT, &decon->sd, ktime_set(0, 0)); | ||||
| irq_end: | ||||
| 	spin_unlock(&decon->slock); | ||||
| 	return IRQ_HANDLED; | ||||
| } | ||||
| 
 | ||||
| int decon_t_get_clocks(struct decon_device *decon) | ||||
| { | ||||
| 	decon->res.pclk = clk_get(decon->dev, "decon_pclk"); | ||||
| 	if (IS_ERR_OR_NULL(decon->res.pclk)) { | ||||
| 		decon_err("failed to get decon_pclk\n"); | ||||
| 		return -ENODEV; | ||||
| 	} | ||||
| 
 | ||||
| 	decon->res.eclk = clk_get(decon->dev, "eclk_user"); | ||||
| 	if (IS_ERR_OR_NULL(decon->res.eclk)) { | ||||
| 		decon_err("failed to get eclk_user\n"); | ||||
| 		return -ENODEV; | ||||
| 	} | ||||
| 
 | ||||
| 	decon->res.eclk_leaf = clk_get(decon->dev, "eclk_leaf"); | ||||
| 	if (IS_ERR_OR_NULL(decon->res.eclk_leaf)) { | ||||
| 		decon_err("failed to get eclk_leaf\n"); | ||||
| 		return -ENODEV; | ||||
| 	} | ||||
| 
 | ||||
| 	return 0; | ||||
| } | ||||
| 
 | ||||
| void decon_t_set_clocks(struct decon_device *decon) | ||||
| { | ||||
| 	struct device *dev = decon->dev; | ||||
| 	struct decon_clocks clks; | ||||
| 	struct decon_param p; | ||||
| 
 | ||||
| 	decon_to_init_param(decon, &p); | ||||
| 	decon_reg_get_clock_ratio(&clks, p.lcd_info); | ||||
| 
 | ||||
| 	/* ECLK */ | ||||
| 	decon_clk_set_rate(dev, decon->res.eclk_leaf, | ||||
| 			NULL, clks.decon[CLK_ID_ECLK] * MHZ); | ||||
| 
 | ||||
| 	decon_dbg("%s: pclk %ld eclk %ld Mhz\n", | ||||
| 		__func__, | ||||
| 		clk_get_rate(decon->res.pclk) / MHZ, | ||||
| 		clk_get_rate(decon->res.eclk_leaf) / MHZ); | ||||
| 
 | ||||
| 	return; | ||||
| } | ||||
| 
 | ||||
| int decon_t_register_irq(struct platform_device *pdev, struct decon_device *decon) | ||||
| { | ||||
| 	struct device *dev = decon->dev; | ||||
| 	struct resource *res; | ||||
| 	int ret = 0; | ||||
| 
 | ||||
| 	/* Get IRQ resource and register IRQ handler. */ | ||||
| 	/* 0: FIFO irq */ | ||||
| 	res = platform_get_resource(pdev, IORESOURCE_IRQ, 0); | ||||
| 	ret = devm_request_irq(dev, res->start, decon_t_irq_handler, 0, | ||||
| 			pdev->name, decon); | ||||
| 	if (ret) { | ||||
| 		decon_err("failed to install irq\n"); | ||||
| 		return ret; | ||||
| 	} | ||||
| 
 | ||||
| 	/* 1: VStatus irq */ | ||||
| 	res = platform_get_resource(pdev, IORESOURCE_IRQ, 1); | ||||
| 	ret = devm_request_irq(dev, res->start, decon_t_irq_handler, 0, | ||||
| 			pdev->name, decon); | ||||
| 	if (ret) { | ||||
| 		decon_err("failed to install irq\n"); | ||||
| 		return ret; | ||||
| 	} | ||||
| 
 | ||||
| 	/* 2: FrameDone irq */ | ||||
| 	res = platform_get_resource(pdev, IORESOURCE_IRQ, 2); | ||||
| 	ret = devm_request_irq(dev, res->start, decon_t_irq_handler, 0, | ||||
| 			pdev->name, decon); | ||||
| 	if (ret) { | ||||
| 		decon_err("failed to install irq\n"); | ||||
| 		return ret; | ||||
| 	} | ||||
| 
 | ||||
| 	/* 3: Extra Interrupts: Resource Conflict irq */ | ||||
| 	res = platform_get_resource(pdev, IORESOURCE_IRQ, 3); | ||||
| 	ret = devm_request_irq(dev, res->start, decon_t_irq_handler, 0, | ||||
| 			pdev->name, decon); | ||||
| 	if (ret) { | ||||
| 		decon_err("failed to install irq\n"); | ||||
| 		return ret; | ||||
| 	} | ||||
| 
 | ||||
| 	return ret; | ||||
| } | ||||
							
								
								
									
										228
									
								
								drivers/video/fbdev/exynos/decon_8890/dsim.h
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										228
									
								
								drivers/video/fbdev/exynos/decon_8890/dsim.h
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,228 @@ | |||
| /* linux/drivers/video/exynos_decon/dsim.h
 | ||||
|  * | ||||
|  * Header file for Samsung MIPI-DSI common driver. | ||||
|  * | ||||
|  * Copyright (c) 2013 Samsung Electronics | ||||
|  * Haowei Li <haowei.li@samsung.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. | ||||
| */ | ||||
| 
 | ||||
| #ifndef __DSIM_H__ | ||||
| #define __DSIM_H__ | ||||
| 
 | ||||
| #include <linux/device.h> | ||||
| #include <linux/fb.h> | ||||
| #include <linux/notifier.h> | ||||
| #include <linux/kernel.h> | ||||
| #include <linux/regulator/consumer.h> | ||||
| #include <linux/delay.h> | ||||
| #include <linux/io.h> | ||||
| 
 | ||||
| #include <media/v4l2-subdev.h> | ||||
| #include <media/media-entity.h> | ||||
| 
 | ||||
| #include "./panels/decon_lcd.h" | ||||
| #include "regs-dsim.h" | ||||
| #include "dsim_common.h" | ||||
| 
 | ||||
| #define DSIM_PAD_SINK		0 | ||||
| #define DSIM_PADS_NUM		1 | ||||
| 
 | ||||
| #define DSIM_RX_FIFO_READ_DONE	(0x30800002) | ||||
| #define DSIM_MAX_RX_FIFO	(64) | ||||
| 
 | ||||
| #define dsim_err(fmt, ...)					\ | ||||
| 	do {							\ | ||||
| 		pr_err(pr_fmt(fmt), ##__VA_ARGS__);		\ | ||||
| 	} while (0) | ||||
| 
 | ||||
| #define dsim_info(fmt, ...)					\ | ||||
| 	do {							\ | ||||
| 		pr_info(pr_fmt(fmt), ##__VA_ARGS__);		\ | ||||
| 	} while (0) | ||||
| 
 | ||||
| #define dsim_dbg(fmt, ...)					\ | ||||
| 	do {							\ | ||||
| 		pr_debug(pr_fmt(fmt), ##__VA_ARGS__);		\ | ||||
| 	} while (0) | ||||
| 
 | ||||
| #define call_panel_ops(q, op, args...)				\ | ||||
| 	(((q)->panel_ops->op) ? ((q)->panel_ops->op(args)) : 0) | ||||
| 
 | ||||
| extern struct dsim_device *dsim0_for_decon; | ||||
| extern struct dsim_device *dsim1_for_decon; | ||||
| extern struct mipi_dsim_lcd_driver s6e3ha0_mipi_lcd_driver; | ||||
| extern struct mipi_dsim_lcd_driver s6e3ha2k_mipi_lcd_driver; | ||||
| extern struct mipi_dsim_lcd_driver s6e3hf2_mipi_lcd_driver; | ||||
| extern struct mipi_dsim_lcd_driver s6e3hf2_wqhd_mipi_lcd_driver; | ||||
| extern struct mipi_dsim_lcd_driver s6e3fa0_mipi_lcd_driver; | ||||
| 
 | ||||
| enum mipi_dsim_pktgo_state { | ||||
| 	DSIM_PKTGO_DISABLED, | ||||
| 	DSIM_PKTGO_STANDBY, | ||||
| 	DSIM_PKTGO_ENABLED | ||||
| }; | ||||
| 
 | ||||
| /* operation state of dsim driver */ | ||||
| enum dsim_state { | ||||
| 	DSIM_STATE_HSCLKEN,	/* HS clock was enabled. */ | ||||
| 	DSIM_STATE_ULPS,	/* DSIM was entered ULPS state */ | ||||
| 	DSIM_STATE_SUSPEND	/* DSIM is suspend state */ | ||||
| }; | ||||
| 
 | ||||
| struct dsim_resources { | ||||
| 	struct clk *pclk; | ||||
| 	struct clk *dphy_esc; | ||||
| 	struct clk *dphy_byte; | ||||
| 	struct clk *rgb_vclk0; | ||||
| 	struct clk *pclk_disp; | ||||
| 	int lcd_power[2]; | ||||
| 	int lcd_reset; | ||||
| }; | ||||
| 
 | ||||
| struct panel_private { | ||||
| 	struct backlight_device *bd; | ||||
| 	unsigned int power; | ||||
| 	unsigned int lcdConnected; | ||||
| }; | ||||
| 
 | ||||
| struct dsim_device { | ||||
| 	struct device *dev; | ||||
| 	void *decon; | ||||
| 	struct dsim_resources res; | ||||
| 	unsigned int irq; | ||||
| 	void __iomem *reg_base; | ||||
| 
 | ||||
| 	enum dsim_state state; | ||||
| 
 | ||||
| 	unsigned int data_lane; | ||||
| 	unsigned long hs_clk; | ||||
| 	unsigned long byte_clk; | ||||
| 	unsigned long escape_clk; | ||||
| 	unsigned char freq_band; | ||||
| 	struct notifier_block fb_notif; | ||||
| 
 | ||||
| 	struct lcd_device	*lcd; | ||||
| 	unsigned int enabled; | ||||
| 	struct decon_lcd lcd_info; | ||||
| 	struct dphy_timing_value	timing; | ||||
| 	int				pktgo; | ||||
| 
 | ||||
| 	int id; | ||||
| 	u32 data_lane_cnt; | ||||
| 	struct mipi_dsim_lcd_driver *panel_ops; | ||||
| 
 | ||||
| 	spinlock_t slock; | ||||
| 	struct mutex lock; | ||||
| 	struct v4l2_subdev sd; | ||||
| 	struct media_pad pad; | ||||
| 	struct panel_private priv; | ||||
| 	struct dsim_clks_param clks_param; | ||||
| 	struct phy *phy; | ||||
| }; | ||||
| 
 | ||||
| /**
 | ||||
|  * driver structure for mipi-dsi based lcd panel. | ||||
|  * | ||||
|  * this structure should be registered by lcd panel driver. | ||||
|  * mipi-dsi driver seeks lcd panel registered through name field | ||||
|  * and calls these callback functions in appropriate time. | ||||
|  */ | ||||
| 
 | ||||
| struct mipi_dsim_lcd_driver { | ||||
| 	int	(*probe)(struct dsim_device *dsim); | ||||
| 	int	(*suspend)(struct dsim_device *dsim); | ||||
| 	int	(*displayon)(struct dsim_device *dsim); | ||||
| 	int	(*resume)(struct dsim_device *dsim); | ||||
| 	int	(*dump)(struct dsim_device *dsim); | ||||
| }; | ||||
| 
 | ||||
| int dsim_write_data(struct dsim_device *dsim, unsigned int data_id, | ||||
| 		unsigned long data0, unsigned int data1); | ||||
| int dsim_read_data(struct dsim_device *dsim, u32 data_id, u32 addr, | ||||
| 		u32 count, u8 *buf); | ||||
| 
 | ||||
| #ifdef CONFIG_DECON_MIPI_DSI_PKTGO | ||||
| void dsim_pkt_go_ready(struct dsim_device *dsim); | ||||
| void dsim_pkt_go_enable(struct dsim_device *dsim, bool enable); | ||||
| #endif | ||||
| 
 | ||||
| static inline struct dsim_device *get_dsim_drvdata(u32 id) | ||||
| { | ||||
| 	if (id) | ||||
| 		return dsim1_for_decon; | ||||
| 	else | ||||
| 		return dsim0_for_decon; | ||||
| } | ||||
| 
 | ||||
| static inline int dsim_rd_data(u32 id, u32 cmd_id, | ||||
| 	 u32 addr, u32 size, u8 *buf) | ||||
| { | ||||
| 	int ret; | ||||
| 	struct dsim_device *dsim = get_dsim_drvdata(id); | ||||
| 
 | ||||
| 	ret = dsim_read_data(dsim, cmd_id, addr, size, buf); | ||||
| 	if (ret) | ||||
| 		return ret; | ||||
| 
 | ||||
| 	return 0; | ||||
| } | ||||
| 
 | ||||
| static inline int dsim_wr_data(u32 id, u32 cmd_id, unsigned long d0, u32 d1) | ||||
| { | ||||
| 	int ret; | ||||
| 	struct dsim_device *dsim = get_dsim_drvdata(id); | ||||
| 
 | ||||
| 	ret = dsim_write_data(dsim, cmd_id, d0, d1); | ||||
| 	if (ret) | ||||
| 		return ret; | ||||
| 
 | ||||
| 	return 0; | ||||
| } | ||||
| 
 | ||||
| /* register access subroutines */ | ||||
| static inline u32 dsim_read(u32 id, u32 reg_id) | ||||
| { | ||||
| 	struct dsim_device *dsim = get_dsim_drvdata(id); | ||||
| 	return readl(dsim->reg_base + reg_id); | ||||
| } | ||||
| 
 | ||||
| static inline u32 dsim_read_mask(u32 id, u32 reg_id, u32 mask) | ||||
| { | ||||
| 	u32 val = dsim_read(id, reg_id); | ||||
| 	val &= (mask); | ||||
| 	return val; | ||||
| } | ||||
| 
 | ||||
| static inline void dsim_write(u32 id, u32 reg_id, u32 val) | ||||
| { | ||||
| 	struct dsim_device *dsim = get_dsim_drvdata(id); | ||||
| 	writel(val, dsim->reg_base + reg_id); | ||||
| } | ||||
| 
 | ||||
| static inline void dsim_write_mask(u32 id, u32 reg_id, u32 val, u32 mask) | ||||
| { | ||||
| 	struct dsim_device *dsim = get_dsim_drvdata(id); | ||||
| 	u32 old = dsim_read(id, reg_id); | ||||
| 
 | ||||
| 	val = (val & mask) | (old & ~mask); | ||||
| 	writel(val, dsim->reg_base + reg_id); | ||||
| } | ||||
| 
 | ||||
| u32 dsim_reg_get_yres(u32 id); | ||||
| u32 dsim_reg_get_xres(u32 id); | ||||
| 
 | ||||
| #define DSIM_IOC_ENTER_ULPS		_IOW('D', 0, u32) | ||||
| #define DSIM_IOC_LCD_OFF		_IOW('D', 1, u32) | ||||
| #define DSIM_IOC_PKT_GO_ENABLE		_IOW('D', 2, u32) | ||||
| #define DSIM_IOC_PKT_GO_DISABLE		_IOW('D', 3, u32) | ||||
| #define DSIM_IOC_PKT_GO_READY		_IOW('D', 4, u32) | ||||
| #define DSIM_IOC_GET_LCD_INFO		_IOW('D', 5, struct decon_lcd *) | ||||
| #define DSIM_IOC_PARTIAL_CMD		_IOW('D', 6, u32) | ||||
| #define DSIM_IOC_SET_PORCH		_IOW('D', 7, struct decon_lcd *) | ||||
| #define DSIM_IOC_DUMP			_IOW('D', 8, u32) | ||||
| 
 | ||||
| #endif /* __DSIM_H__ */ | ||||
							
								
								
									
										169
									
								
								drivers/video/fbdev/exynos/decon_8890/dsim_common.h
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										169
									
								
								drivers/video/fbdev/exynos/decon_8890/dsim_common.h
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,169 @@ | |||
| /* dsim_common.h
 | ||||
|  * | ||||
|  * Header file for Samsung MIPI-DSI lowlevel driver. | ||||
|  * | ||||
|  * Copyright (c) 2014 Samsung Electronics | ||||
|  * Jiun Yu <jiun.yu@samsung.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. | ||||
| */ | ||||
| 
 | ||||
| #ifndef _DSIM_COMMON_H_ | ||||
| #define _DSIM_COMMON_H_ | ||||
| 
 | ||||
| #include "./panels/decon_lcd.h" | ||||
| 
 | ||||
| #define DSIM_PIXEL_FORMAT_RGB24		0x7 | ||||
| #define DSIM_PIXEL_FORMAT_RGB18		0x6 | ||||
| #define DSIM_PIXEL_FORMAT_RGB18_PACKED	0x5 | ||||
| 
 | ||||
| /* define DSI lane types. */ | ||||
| enum { | ||||
| 	DSIM_LANE_CLOCK	= (1 << 0), | ||||
| 	DSIM_LANE_DATA0	= (1 << 1), | ||||
| 	DSIM_LANE_DATA1	= (1 << 2), | ||||
| 	DSIM_LANE_DATA2	= (1 << 3), | ||||
| 	DSIM_LANE_DATA3	= (1 << 4), | ||||
| }; | ||||
| 
 | ||||
| struct dsim_pll_param { | ||||
| 	u32 p; | ||||
| 	u32 m; | ||||
| 	u32 s; | ||||
| 	u32 pll_freq; /* in/out parameter: Mhz */ | ||||
| }; | ||||
| 
 | ||||
| struct dsim_clks { | ||||
| 	u32 hs_clk; | ||||
| 	u32 esc_clk; | ||||
| 	u32 byte_clk; | ||||
| }; | ||||
| 
 | ||||
| struct dphy_timing_value { | ||||
| 	u32 bps; | ||||
| 	u32 clk_prepare; | ||||
| 	u32 clk_zero; | ||||
| 	u32 clk_post; | ||||
| 	u32 clk_trail; | ||||
| 	u32 hs_prepare; | ||||
| 	u32 hs_zero; | ||||
| 	u32 hs_trail; | ||||
| 	u32 lpx; | ||||
| 	u32 hs_exit; | ||||
| 	u32 b_dphyctl; | ||||
| }; | ||||
| 
 | ||||
| struct dsim_clks_param { | ||||
| 	struct dsim_clks clks; | ||||
| 	struct dsim_pll_param pll; | ||||
| 	struct dphy_timing_value t; | ||||
| 
 | ||||
| 	u32 esc_div; | ||||
| }; | ||||
| 
 | ||||
| /* CAL APIs list */ | ||||
| int dsim_reg_init(u32 id, struct decon_lcd *lcd_info, | ||||
| 			u32 data_lane_cnt, struct dsim_clks *clks); | ||||
| void dsim_reg_init_probe(u32 id, struct decon_lcd *lcd_info, | ||||
| 			u32 data_lane_cnt, struct dsim_clks *clks); | ||||
| int dsim_reg_set_clocks(u32 id, struct dsim_clks *clks, struct stdphy_pms *dphy_pms, u32 en); | ||||
| int dsim_reg_set_lanes(u32 id, u32 lanes, u32 en); | ||||
| int dsim_reg_set_hs_clock(u32 id, u32 en); | ||||
| void dsim_reg_set_int(u32 id, u32 en); | ||||
| int dsim_reg_set_ulps(u32 id, u32 en, u32 lanes); | ||||
| int dsim_reg_set_smddi_ulps(u32 id, u32 en, u32 lanes); | ||||
| 
 | ||||
| /* CAL raw functions list */ | ||||
| void dsim_reg_sw_reset(u32 id); | ||||
| void dsim_reg_dphy_reset(u32 id); | ||||
| void dsim_reg_funtion_reset(u32 id); | ||||
| void dsim_reg_dp_dn_swap(u32 id, u32 en); | ||||
| void dsim_reg_set_num_of_lane(u32 id, u32 lane); | ||||
| void dsim_reg_enable_lane(u32 id, u32 lane, u32 en); | ||||
| void dsim_reg_set_pll_freq(u32 id, u32 p, u32 m, u32 s); | ||||
| void dsim_reg_pll_stable_time(u32 id); | ||||
| void dsim_reg_set_dphy_timing_values(u32 id, struct dphy_timing_value *t); | ||||
| void dsim_reg_clear_int(u32 id, u32 int_src); | ||||
| void dsim_reg_clear_int_all(u32 id); | ||||
| void dsim_reg_set_pll(u32 id, u32 en); | ||||
| u32 dsim_reg_is_pll_stable(u32 id); | ||||
| int dsim_reg_enable_pll(u32 id, u32 en); | ||||
| void dsim_reg_set_byte_clock(u32 id, u32 en); | ||||
| void dsim_reg_set_esc_clk_prescaler(u32 id, u32 en, u32 p); | ||||
| void dsim_reg_set_esc_clk_on_lane(u32 id, u32 en, u32 lane); | ||||
| u32 dsim_reg_wait_lane_stop_state(u32 id); | ||||
| void dsim_reg_set_stop_state_cnt(u32 id); | ||||
| void dsim_reg_set_bta_timeout(u32 id); | ||||
| void dsim_reg_set_lpdr_timeout(u32 id); | ||||
| void dsim_reg_set_porch(u32 id, struct decon_lcd *lcd); | ||||
| void dsim_reg_set_pixel_format(u32 id, u32 pixformat); | ||||
| void dsim_reg_set_config(u32 id, struct decon_lcd *lcd_info, u32 data_lane_cnt); | ||||
| void dsim_reg_set_cmd_transfer_mode(u32 id, u32 lp); | ||||
| void dsim_reg_set_multipix(u32 id, u32 multipix); | ||||
| void dsim_reg_set_vc_id(u32 id, u32 vcid); | ||||
| void dsim_reg_set_video_mode(u32 id, u32 mode); | ||||
| void dsim_reg_enable_dsc(u32 id, u32 en); | ||||
| void dsim_reg_disable_hsa(u32 id, u32 en); | ||||
| void dsim_reg_disable_hbp(u32 id, u32 en); | ||||
| void dsim_reg_disable_hfp(u32 id, u32 en); | ||||
| void dsim_reg_disable_hse(u32 id, u32 en); | ||||
| void dsim_reg_set_hsync_preserve(u32 id, u32 en); | ||||
| void dsim_reg_set_burst_mode(u32 id, u32 burst); | ||||
| void dsim_reg_set_sync_inform(u32 id, u32 inform); | ||||
| void dsim_reg_set_cmdallow(u32 id, u32 cmdallow); | ||||
| void dsim_reg_set_stable_vfp(u32 id, u32 stablevfp); | ||||
| void dsim_reg_set_vbp(u32 id, u32 vbp); | ||||
| void dsim_reg_set_hfp(u32 id, u32 hfp); | ||||
| void dsim_reg_set_hbp(u32 id, u32 hbp); | ||||
| void dsim_reg_set_vsa(u32 id, u32 vsa); | ||||
| void dsim_reg_set_hsa(u32 id, u32 hsa); | ||||
| void dsim_reg_set_vresol(u32 id, u32 vresol); | ||||
| void dsim_reg_set_hresol(u32 id, u32 hresol, struct decon_lcd *lcd); | ||||
| void dsim_reg_set_multi_packet_count(u32 id, u32 multipacketcnt); | ||||
| void dsim_reg_set_command_control(u32 id, u32 cmdcontrol); | ||||
| void dsim_reg_set_time_stable_vfp(u32 id, u32 stablevfp); | ||||
| void dsim_reg_set_time_vsync_timeout(u32 id, u32 vsynctout); | ||||
| void dsim_reg_set_time_te_protect_on(u32 id, u32 teprotecton); | ||||
| void dsim_reg_set_time_te_timeout(u32 id, u32 tetout); | ||||
| void dsim_reg_set_hsync_timeout(u32 id, u32 hsynctout); | ||||
| void dsim_reg_enable_mflush(u32 id, u32 en); | ||||
| void dsim_reg_enable_noncontinuous_clock(u32 id, u32 en); | ||||
| void dsim_reg_enable_clocklane_stop_start(u32 id, u32 en); | ||||
| void dsim_reg_enable_packetgo(u32 id, u32 en); | ||||
| void dsim_reg_set_packetgo_ready(u32 id); | ||||
| void dsim_reg_enable_multi_command_packet(u32 id, u32 en); | ||||
| void dsim_reg_enable_shadow(u32 id, u32 en); | ||||
| void dsim_reg_enable_hs_clock(u32 id, u32 en); | ||||
| void dsim_reg_enable_byte_clock(u32 id, u32 en); | ||||
| u32 dsim_reg_is_hs_clk_ready(u32 id); | ||||
| void dsim_reg_enable_per_frame_read(u32 id, u32 en); | ||||
| void dsim_reg_enable_qchannel(u32 id, u32 en); | ||||
| int dsim_reg_wait_hs_clk_ready(u32 id); | ||||
| void dsim_reg_set_fifo_ctrl(u32 id, u32 cfg); | ||||
| void dsim_reg_force_dphy_stop_state(u32 id, u32 en); | ||||
| void dsim_reg_wr_tx_header(u32 id, u32 data_id, unsigned long data0, u32 data1); | ||||
| void dsim_reg_wr_tx_payload(u32 id, u32 payload); | ||||
| void dsim_reg_enter_ulps(u32 id, u32 enter); | ||||
| void dsim_reg_exit_ulps(u32 id, u32 exit); | ||||
| int dsim_reg_set_ulps_by_ddi(u32 id, u32 ddi_type, u32 lanes, u32 en); | ||||
| int dsim_reg_wait_enter_ulps_state(u32 id, u32 lanes); | ||||
| int dsim_reg_wait_exit_ulps_state(u32 id); | ||||
| void dsim_reg_set_standby(u32 id, u32 en); | ||||
| void dsim_reg_set_bist(u32 id, u32 en, u32 vfp, u32 format, u32 type); | ||||
| void dsim_reg_set_packet_ctrl(u32 id); | ||||
| void dsim_reg_enable_loopback(u32 id, u32 en); | ||||
| void dsim_reg_set_loopback_id(u32 id, u32 en); | ||||
| void dsim_reg_set_pkt_go_enable(u32 id, bool en); | ||||
| void dsim_reg_set_pkt_go_ready(u32 id); | ||||
| void dsim_reg_set_pkt_go_cnt(u32 id, unsigned int count); | ||||
| void dsim_reg_set_shadow(u32 id, u32 en); | ||||
| void dsim_reg_shadow_update(u32 id); | ||||
| int dsim_reg_exit_ulps_and_start(u32 id, u32 ddi_type, u32 lanes); | ||||
| int dsim_reg_stop_and_enter_ulps(u32 id, u32 ddi_type, u32 lanes); | ||||
| void dsim_reg_start(u32 id, struct dsim_clks *clks, u32 lanes); | ||||
| void dsim_reg_stop(u32 id, u32 lanes); | ||||
| void dsim_reg_set_partial_update(u32 id, struct decon_lcd *lcd_info); | ||||
| 
 | ||||
| #endif /* _DSIM_COMMON_H_ */ | ||||
							
								
								
									
										1471
									
								
								drivers/video/fbdev/exynos/decon_8890/dsim_drv.c
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										1471
									
								
								drivers/video/fbdev/exynos/decon_8890/dsim_drv.c
									
										
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load diff
											
										
									
								
							
							
								
								
									
										1391
									
								
								drivers/video/fbdev/exynos/decon_8890/dsim_reg_8890.c
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										1391
									
								
								drivers/video/fbdev/exynos/decon_8890/dsim_reg_8890.c
									
										
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load diff
											
										
									
								
							
							
								
								
									
										7
									
								
								drivers/video/fbdev/exynos/decon_8890/panels/Kconfig
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										7
									
								
								drivers/video/fbdev/exynos/decon_8890/panels/Kconfig
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,7 @@ | |||
| config EXYNOS_DECON_LCD | ||||
| 	depends on EXYNOS_DECON_8890 | ||||
| 	bool "Select LCD panel driver" | ||||
| 
 | ||||
| config EXYNOS_DECON_LCD_S6E3HA2K | ||||
| 	depends on EXYNOS_DECON_LCD && EXYNOS_MIPI_DSI | ||||
| 	tristate "S6E3HA2K AMOLED WQHD LCD driver(1440 x 2560)" | ||||
							
								
								
									
										1
									
								
								drivers/video/fbdev/exynos/decon_8890/panels/Makefile
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								drivers/video/fbdev/exynos/decon_8890/panels/Makefile
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1 @@ | |||
| obj-$(CONFIG_EXYNOS_DECON_LCD_S6E3HA2K)	+= s6e3ha2k_mipi_lcd.o s6e3ha2k_lcd_ctrl.o | ||||
							
								
								
									
										72
									
								
								drivers/video/fbdev/exynos/decon_8890/panels/decon_lcd.h
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										72
									
								
								drivers/video/fbdev/exynos/decon_8890/panels/decon_lcd.h
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,72 @@ | |||
| /* drivers/video/exynos_decon/lcd.h
 | ||||
|  * | ||||
|  * Copyright (c) 2011 Samsung Electronics | ||||
|  * 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. | ||||
| */ | ||||
| 
 | ||||
| #ifndef __DECON_LCD__ | ||||
| #define __DECON_LCD__ | ||||
| 
 | ||||
| enum decon_psr_mode { | ||||
| 	DECON_VIDEO_MODE = 0, | ||||
| 	DECON_DP_PSR_MODE = 1, | ||||
| 	DECON_MIPI_COMMAND_MODE = 2, | ||||
| }; | ||||
| 
 | ||||
| /* Mic ratio: 0: 1/2 ratio, 1: 1/3 ratio */ | ||||
| enum decon_mic_comp_ratio { | ||||
| 	MIC_COMP_RATIO_1_2 = 0, | ||||
| 	MIC_COMP_RATIO_1_3 = 1, | ||||
| 	MIC_COMP_BYPASS | ||||
| }; | ||||
| 
 | ||||
| enum mic_ver { | ||||
| 	MIC_VER_1_1, | ||||
| 	MIC_VER_1_2, | ||||
| 	MIC_VER_2_0, | ||||
| }; | ||||
| 
 | ||||
| enum type_of_ddi { | ||||
| 	TYPE_OF_SM_DDI = 0, | ||||
| 	TYPE_OF_MAGNA_DDI, | ||||
| 	TYPE_OF_NORMAL_DDI, | ||||
| }; | ||||
| 
 | ||||
| struct stdphy_pms { | ||||
| 	unsigned int p; | ||||
| 	unsigned int m; | ||||
| 	unsigned int s; | ||||
| }; | ||||
| 
 | ||||
| struct decon_lcd { | ||||
| 	enum decon_psr_mode mode; | ||||
| 	unsigned int vfp; | ||||
| 	unsigned int vbp; | ||||
| 	unsigned int hfp; | ||||
| 	unsigned int hbp; | ||||
| 
 | ||||
| 	unsigned int vsa; | ||||
| 	unsigned int hsa; | ||||
| 
 | ||||
| 	unsigned int xres; | ||||
| 	unsigned int yres; | ||||
| 
 | ||||
| 	unsigned int width; | ||||
| 	unsigned int height; | ||||
| 
 | ||||
| 	unsigned int hs_clk; | ||||
| 	struct stdphy_pms dphy_pms; | ||||
| 	unsigned int esc_clk; | ||||
| 
 | ||||
| 	unsigned int fps; | ||||
| 	unsigned int mic_enabled; | ||||
| 	enum decon_mic_comp_ratio mic_ratio; | ||||
| 	unsigned int dsc_enabled; | ||||
| 	unsigned int dsc_slice; | ||||
| 	enum mic_ver mic_ver; | ||||
| 	enum type_of_ddi ddi_type; | ||||
| }; | ||||
| 
 | ||||
| #endif | ||||
							
								
								
									
										24
									
								
								drivers/video/fbdev/exynos/decon_8890/panels/lcd_ctrl.h
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										24
									
								
								drivers/video/fbdev/exynos/decon_8890/panels/lcd_ctrl.h
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,24 @@ | |||
| /* linux/drivers/video/decon_display/s6e3fa0_gamma.h
 | ||||
|  * | ||||
|  * Copyright (c) 2012 Samsung Electronics Co., Ltd. | ||||
|  * | ||||
|  * Haowe Li <haowei.li@samsung.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. | ||||
| */ | ||||
| 
 | ||||
| #ifndef __LCD_CTRL_H__ | ||||
| #define __LCD_CTRL_H__ | ||||
| 
 | ||||
| #include "decon_lcd.h" | ||||
| 
 | ||||
| void lcd_init(int id, struct decon_lcd *lcd); | ||||
| void lcd_enable(int id); | ||||
| void lcd_disable(int id); | ||||
| int lcd_gamma_ctrl(int id, unsigned int backlightlevel); | ||||
| int lcd_gamma_update(int id); | ||||
| int lcd_dump(int id); | ||||
| 
 | ||||
| #endif /* __LCD_CTRL_H__ */ | ||||
							
								
								
									
										364
									
								
								drivers/video/fbdev/exynos/decon_8890/panels/s6e3ha2k_lcd_ctrl.c
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										364
									
								
								drivers/video/fbdev/exynos/decon_8890/panels/s6e3ha2k_lcd_ctrl.c
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,364 @@ | |||
| /*
 | ||||
|  * drivers/video/decon/panels/s6e3ha2k_lcd_ctrl.c | ||||
|  * | ||||
|  * Samsung SoC MIPI LCD CONTROL functions | ||||
|  * | ||||
|  * Copyright (c) 2014 Samsung Electronics | ||||
|  * | ||||
|  * Jiun Yu, <jiun.yu@samsung.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. | ||||
| */ | ||||
| 
 | ||||
| #include "s6e3ha2k_param.h" | ||||
| #include "lcd_ctrl.h" | ||||
| 
 | ||||
| /* use FW_TEST definition when you test CAL on firmware */ | ||||
| /* #define FW_TEST */ | ||||
| #ifdef FW_TEST | ||||
| #include "../dsim_fw.h" | ||||
| #include "mipi_display.h" | ||||
| #else | ||||
| #include "../dsim.h" | ||||
| #include <video/mipi_display.h> | ||||
| #endif | ||||
| 
 | ||||
| /* Porch values. It depends on command or video mode */ | ||||
| #define S6E3HA2K_CMD_VBP	15 | ||||
| #define S6E3HA2K_CMD_VFP	1 | ||||
| #define S6E3HA2K_CMD_VSA	1 | ||||
| #define S6E3HA2K_CMD_HBP	1 | ||||
| #define S6E3HA2K_CMD_HFP	1 | ||||
| #define S6E3HA2K_CMD_HSA	1 | ||||
| 
 | ||||
| /* These need to define */ | ||||
| #define S6E3HA2K_VIDEO_VBP	15 | ||||
| #define S6E3HA2K_VIDEO_VFP	1 | ||||
| #define S6E3HA2K_VIDEO_VSA	1 | ||||
| #define S6E3HA2K_VIDEO_HBP	20 | ||||
| #define S6E3HA2K_VIDEO_HFP	20 | ||||
| #define S6E3HA2K_VIDEO_HSA	20 | ||||
| 
 | ||||
| #define S6E3HA2K_HORIZONTAL	1440 | ||||
| #define S6E3HA2K_VERTICAL	2560 | ||||
| 
 | ||||
| #ifdef FW_TEST /* This information is moved to DT */ | ||||
| #define CONFIG_FB_I80_COMMAND_MODE | ||||
| 
 | ||||
| struct decon_lcd s6e3ha2k_lcd_info = { | ||||
| #ifdef CONFIG_FB_I80_COMMAND_MODE | ||||
| 	.mode = DECON_MIPI_COMMAND_MODE, | ||||
| 	.vfp = S6E3HA2K_CMD_VFP, | ||||
| 	.vbp = S6E3HA2K_CMD_VBP, | ||||
| 	.hfp = S6E3HA2K_CMD_HFP, | ||||
| 	.hbp = S6E3HA2K_CMD_HBP, | ||||
| 	.vsa = S6E3HA2K_CMD_VSA, | ||||
| 	.hsa = S6E3HA2K_CMD_HSA, | ||||
| #else | ||||
| 	.mode = DECON_VIDEO_MODE, | ||||
| 	.vfp = S6E3HA2K_VIDEO_VFP, | ||||
| 	.vbp = S6E3HA2K_VIDEO_VBP, | ||||
| 	.hfp = S6E3HA2K_VIDEO_HFP, | ||||
| 	.hbp = S6E3HA2K_VIDEO_HBP, | ||||
| 	.vsa = S6E3HA2K_VIDEO_VSA, | ||||
| 	.hsa = S6E3HA2K_VIDEO_HSA, | ||||
| #endif | ||||
| 	.xres = S6E3HA2K_HORIZONTAL, | ||||
| 	.yres = S6E3HA2K_VERTICAL, | ||||
| 
 | ||||
| 	/* Maybe, width and height will be removed */ | ||||
| 	.width = 70, | ||||
| 	.height = 121, | ||||
| 
 | ||||
| 	/* Mhz */ | ||||
| 	.hs_clk = 1100, | ||||
| 	.esc_clk = 20, | ||||
| 
 | ||||
| 	.fps = 60, | ||||
| 	.mic_enabled = 1, | ||||
| 	.mic_ver = MIC_VER_1_2, | ||||
| }; | ||||
| #endif | ||||
| 
 | ||||
| /*
 | ||||
|  * 3HA2K lcd init sequence | ||||
|  * | ||||
|  * Parameters | ||||
|  *	- mic_enabled : if mic is enabled, MIC_ENABLE command must be sent | ||||
|  *	- mode : LCD init sequence depends on command or video mode | ||||
|  */ | ||||
| 
 | ||||
| void lcd_init(int id, struct decon_lcd *lcd) | ||||
| { | ||||
| 	if (dsim_wr_data(id, MIPI_DSI_DCS_LONG_WRITE, (unsigned long)SEQ_TEST_KEY_ON_F0, | ||||
| 				ARRAY_SIZE(SEQ_TEST_KEY_ON_F0)) < 0) | ||||
| 		dsim_err("fail to write KEY_ON init command.\n"); | ||||
| 
 | ||||
| 	if (dsim_wr_data(id, MIPI_DSI_DCS_LONG_WRITE, (unsigned long)SEQ_REG_F2, | ||||
| 				ARRAY_SIZE(SEQ_REG_F2)) < 0) | ||||
| 		dsim_err("fail to write F2 init command.\n"); | ||||
| 
 | ||||
| 	if (lcd->mic_enabled) | ||||
| 		if (dsim_wr_data(id, MIPI_DSI_DCS_LONG_WRITE, (unsigned long)SEQ_REG_F9, | ||||
| 					ARRAY_SIZE(SEQ_REG_F9)) < 0) | ||||
| 			dsim_err("fail to write F9 init command.\n"); | ||||
| 
 | ||||
| 	if (dsim_wr_data(id, MIPI_DSI_DCS_SHORT_WRITE, (unsigned long)SEQ_SLEEP_OUT[0], 0) < 0) | ||||
| 		dsim_err("fail to write SLEEP_OUT init command.\n"); | ||||
| 
 | ||||
| 	msleep(10); | ||||
| 
 | ||||
| 	if (dsim_wr_data(id, MIPI_DSI_DCS_LONG_WRITE, (unsigned long)SEQ_TEST_KEY_ON_F0, | ||||
| 				ARRAY_SIZE(SEQ_TEST_KEY_ON_F0)) < 0) | ||||
| 		dsim_err("fail to write KEY_ON init command.\n"); | ||||
| 
 | ||||
| 	/* TE rising time change : 10 line earlier */ | ||||
| 	if (dsim_wr_data(id, MIPI_DSI_DCS_LONG_WRITE, (unsigned long)SEQ_TE_START_SETTING, | ||||
| 				ARRAY_SIZE(SEQ_TE_START_SETTING)) < 0) | ||||
| 		dsim_err("fail to write TE_START_SETTING command.\n"); | ||||
| 
 | ||||
| 	if (dsim_wr_data(id, MIPI_DSI_DCS_LONG_WRITE, (unsigned long)SEQ_REG_F2, | ||||
| 				ARRAY_SIZE(SEQ_REG_F2)) < 0) | ||||
| 		dsim_err("fail to write F2 init command.\n"); | ||||
| 
 | ||||
| 	if (dsim_wr_data(id, MIPI_DSI_DCS_SHORT_WRITE, SEQ_TE_ON[0], 0) < 0) | ||||
| 		dsim_err("fail to write TE_on init command.\n"); | ||||
| 
 | ||||
| 	if (dsim_wr_data(id, MIPI_DSI_DCS_LONG_WRITE, (unsigned long)SEQ_TOUCH_HSYNC, | ||||
| 				ARRAY_SIZE(SEQ_TOUCH_HSYNC)) < 0) | ||||
| 		dsim_err("fail to write TOUCH_HSYNC init command.\n"); | ||||
| 
 | ||||
| 	if (dsim_wr_data(id, MIPI_DSI_DCS_LONG_WRITE, (unsigned long)SEQ_PENTILE_CONTROL, | ||||
| 				ARRAY_SIZE(SEQ_PENTILE_CONTROL)) < 0) | ||||
| 		dsim_err("fail to write PENTILE_CONTROL init command.\n"); | ||||
| 
 | ||||
| 	if (dsim_wr_data(id, MIPI_DSI_DCS_LONG_WRITE, (unsigned long)SEQ_COLUMN_ADDRESS, | ||||
| 				ARRAY_SIZE(SEQ_COLUMN_ADDRESS)) < 0) | ||||
| 		dsim_err("fail to write COLUMN_ADDRESS init command.\n"); | ||||
| 
 | ||||
| 	if (dsim_wr_data(id, MIPI_DSI_DCS_LONG_WRITE, (unsigned long)SEQ_GAMMA_CONDITION_SET, | ||||
| 				ARRAY_SIZE(SEQ_GAMMA_CONDITION_SET)) < 0) | ||||
| 		dsim_err("fail to write GAMMA_CONDITION_SET init command.\n"); | ||||
| 
 | ||||
| 	if (dsim_wr_data(id, MIPI_DSI_DCS_LONG_WRITE, (unsigned long)SEQ_AID_SET, | ||||
| 				ARRAY_SIZE(SEQ_AID_SET)) < 0) | ||||
| 		dsim_err("fail to write AID_SET init command.\n"); | ||||
| 
 | ||||
| 	if (dsim_wr_data(id, MIPI_DSI_DCS_LONG_WRITE, (unsigned long)SEQ_ELVSS_SET, | ||||
| 				ARRAY_SIZE(SEQ_ELVSS_SET)) < 0) | ||||
| 		dsim_err("fail to write ELVSS_SET init command.\n"); | ||||
| 
 | ||||
| 	if (dsim_wr_data(id, MIPI_DSI_DCS_LONG_WRITE, (unsigned long)SEQ_GAMMA_UPDATE, | ||||
| 				ARRAY_SIZE(SEQ_GAMMA_UPDATE)) < 0) | ||||
| 		dsim_err("fail to write GAMMA_UPDATE init command.\n"); | ||||
| 
 | ||||
| 	if (dsim_wr_data(id, MIPI_DSI_DCS_LONG_WRITE, (unsigned long)SEQ_ACL_OFF, | ||||
| 				ARRAY_SIZE(SEQ_ACL_OFF)) < 0) | ||||
| 		dsim_err("fail to write ACL_OFF init command.\n"); | ||||
| 
 | ||||
| 	if (dsim_wr_data(id, MIPI_DSI_DCS_LONG_WRITE, (unsigned long)SEQ_ACL_OPR, | ||||
| 				ARRAY_SIZE(SEQ_ACL_OPR)) < 0) | ||||
| 		dsim_err("fail to write ACL_OPR init command.\n"); | ||||
| 
 | ||||
| 	if (dsim_wr_data(id, MIPI_DSI_DCS_LONG_WRITE, (unsigned long)SEQ_HBM_OFF, | ||||
| 				ARRAY_SIZE(SEQ_HBM_OFF)) < 0) | ||||
| 		dsim_err("fail to write HBM_OFF init command.\n"); | ||||
| 
 | ||||
| 	if (dsim_wr_data(id, MIPI_DSI_DCS_LONG_WRITE, (unsigned long)SEQ_TSET_GLOBAL, | ||||
| 				ARRAY_SIZE(SEQ_TSET_GLOBAL)) < 0) | ||||
| 		dsim_err("fail to write TSET_GLOBAL init command.\n"); | ||||
| 
 | ||||
| 	if (dsim_wr_data(id, MIPI_DSI_DCS_LONG_WRITE, (unsigned long)SEQ_TSET, | ||||
| 				ARRAY_SIZE(SEQ_TSET)) < 0) | ||||
| 		dsim_err("fail to write TSET init command.\n"); | ||||
| 
 | ||||
| 	if (dsim_wr_data(id, MIPI_DSI_DCS_LONG_WRITE, (unsigned long)SEQ_TEST_KEY_OFF_F0, | ||||
| 				ARRAY_SIZE(SEQ_TEST_KEY_OFF_F0)) < 0) | ||||
| 		dsim_err("fail to write KEY_OFF init command.\n"); | ||||
| 
 | ||||
| 	/* Added 120ms delay before SEQ_DISPLAY_ON */ | ||||
| 	msleep(120); | ||||
| } | ||||
| 
 | ||||
| void lcd_enable(int id) | ||||
| { | ||||
| 	if (dsim_wr_data(id, MIPI_DSI_DCS_SHORT_WRITE, (unsigned long)SEQ_DISPLAY_ON[0], 0) < 0) | ||||
| 		dsim_err("fail to write DISPLAY_ON command.\n"); | ||||
| } | ||||
| 
 | ||||
| void lcd_disable(int id) | ||||
| { | ||||
| 	/* This function needs to implement */ | ||||
| } | ||||
| 
 | ||||
| /*
 | ||||
|  * Set gamma values | ||||
|  * | ||||
|  * Parameter | ||||
|  *	- backlightlevel : It is from 0 to 26. | ||||
|  */ | ||||
| int lcd_gamma_ctrl(int id, u32 backlightlevel) | ||||
| { | ||||
| /* This will be implemented
 | ||||
| 	int ret; | ||||
| 	ret = dsim_wr_data(id, MIPI_DSI_DCS_LONG_WRITE, (u32)gamma22_table[backlightlevel], | ||||
| 			GAMMA_PARAM_SIZE); | ||||
| 	if (ret) { | ||||
| 		dsim_err("fail to write gamma value.\n"); | ||||
| 		return ret; | ||||
| 	} | ||||
| */ | ||||
| 	return 0; | ||||
| } | ||||
| 
 | ||||
| int lcd_gamma_update(int id) | ||||
| { | ||||
| /* This will be implemented
 | ||||
| 	int ret; | ||||
| 	ret = dsim_wr_data(id, MIPI_DSI_DCS_LONG_WRITE, (u32)SEQ_GAMMA_UPDATE, | ||||
| 			ARRAY_SIZE(SEQ_GAMMA_UPDATE)); | ||||
| 	if (ret) { | ||||
| 		dsim_err("fail to update gamma value.\n"); | ||||
| 		return ret; | ||||
| 	} | ||||
| */ | ||||
| 	return 0; | ||||
| } | ||||
| 
 | ||||
| int dsim_write_by_panel(int id, const u8 *cmd, u32 cmdSize) | ||||
| { | ||||
| 	int ret; | ||||
| 
 | ||||
| 	if (cmdSize == 1) | ||||
| 		ret = dsim_wr_data(id, MIPI_DSI_DCS_SHORT_WRITE, cmd[0], 0); | ||||
| 	else if (cmdSize == 2) | ||||
| 		ret = dsim_wr_data(id, MIPI_DSI_DCS_SHORT_WRITE_PARAM, cmd[0], cmd[1]); | ||||
| 	else | ||||
| 		ret = dsim_wr_data(id, MIPI_DSI_DCS_LONG_WRITE, (unsigned long)cmd, cmdSize); | ||||
| 
 | ||||
| 	return ret; | ||||
| } | ||||
| 
 | ||||
| int dsim_read_from_panel(int id, u8 addr, u32 size, u8 *buf) | ||||
| { | ||||
| 	int ret; | ||||
| 
 | ||||
| 	ret = dsim_rd_data(id, MIPI_DSI_DCS_READ, (u32)addr, size, buf); | ||||
| 
 | ||||
| 	return ret; | ||||
| } | ||||
| 
 | ||||
| static int s6e3ha2_wqhd_dump(int dsim) | ||||
| { | ||||
| 	int ret = 0; | ||||
| 	unsigned char id[S6E3HA2_RD_LEN]; | ||||
| 	unsigned char rddpm[S6E3HA2_RD_LEN + 1]; | ||||
| 	unsigned char rddsm[S6E3HA2_RD_LEN + 1]; | ||||
| 	unsigned char err_buf[S6E3HA2_RD_LEN + 1]; | ||||
| 
 | ||||
| 	dsim_info(" + %s\n", __func__); | ||||
| 	ret = dsim_write_by_panel(dsim, SEQ_TEST_KEY_ON_F0, ARRAY_SIZE(SEQ_TEST_KEY_ON_F0)); | ||||
| 	if (ret < 0) { | ||||
| 		dsim_err("%s : fail to write CMD : SEQ_TEST_KEY_ON_F0\n", __func__); | ||||
| 	} | ||||
| 
 | ||||
| 	ret = dsim_write_by_panel(dsim, SEQ_TEST_KEY_ON_FC, ARRAY_SIZE(SEQ_TEST_KEY_ON_FC)); | ||||
| 	if (ret < 0) { | ||||
| 		dsim_err("%s : fail to write CMD : SEQ_TEST_KEY_ON_FC\n", __func__); | ||||
| 	} | ||||
| 
 | ||||
| 	ret = dsim_read_from_panel(dsim, 0xEA, S6E3HA2_RD_LEN, err_buf); | ||||
| 	if (ret != S6E3HA2_RD_LEN) { | ||||
| 		dsim_err("%s : can't read Panel's EA Reg\n",__func__); | ||||
| 		goto dump_exit; | ||||
| 	} | ||||
| 
 | ||||
| 	dsim_dbg("=== Panel's 0xEA Reg Value ===\n"); | ||||
| 	dsim_dbg("* 0xEA : buf[0] = %x\n", err_buf[0]); | ||||
| 	dsim_dbg("* 0xEA : buf[1] = %x\n", err_buf[1]); | ||||
| 
 | ||||
| 	ret = dsim_read_from_panel(dsim, S6E3HA2_RDDPM_ADDR, S6E3HA2_RD_LEN, rddpm); | ||||
| 	if (ret != S6E3HA2_RD_LEN) { | ||||
| 		dsim_err("%s : can't read RDDPM Reg\n",__func__); | ||||
| 		goto dump_exit; | ||||
| 	} | ||||
| 
 | ||||
| 	dsim_info("=== Panel's RDDPM Reg Value : %x ===\n", rddpm[0]); | ||||
| 
 | ||||
| 	if (rddpm[0] & 0x80) | ||||
| 		dsim_info("* Booster Voltage Status : ON\n"); | ||||
| 	else | ||||
| 		dsim_info("* Booster Voltage Status : OFF\n"); | ||||
| 
 | ||||
| 	if (rddpm[0] & 0x40) | ||||
| 		dsim_info("* Idle Mode : On\n"); | ||||
| 	else | ||||
| 		dsim_info("* Idle Mode : OFF\n"); | ||||
| 
 | ||||
| 	if (rddpm[0] & 0x20) | ||||
| 		dsim_info("* Partial Mode : On\n"); | ||||
| 	else | ||||
| 		dsim_info("* Partial Mode : OFF\n"); | ||||
| 
 | ||||
| 	if (rddpm[0] & 0x10) | ||||
| 		dsim_info("* Sleep OUT and Working Ok\n"); | ||||
| 	else | ||||
| 		dsim_info("* Sleep IN\n"); | ||||
| 
 | ||||
| 	if (rddpm[0] & 0x08) | ||||
| 		dsim_info("* Normal Mode On and Working Ok\n"); | ||||
| 	else | ||||
| 		dsim_info("* Sleep IN\n"); | ||||
| 
 | ||||
| 	if (rddpm[0] & 0x04) | ||||
| 		dsim_info("* Display On and Working Ok\n"); | ||||
| 	else | ||||
| 		dsim_info("* Display Off\n"); | ||||
| 
 | ||||
| 	ret = dsim_read_from_panel(dsim, S6E3HA2_RDDSM_ADDR, S6E3HA2_RD_LEN, rddsm); | ||||
| 	if (ret != S6E3HA2_RD_LEN) { | ||||
| 		dsim_err("%s : can't read RDDSM Reg\n",__func__); | ||||
| 		goto dump_exit; | ||||
| 	} | ||||
| 
 | ||||
| 	dsim_info("=== Panel's RDDSM Reg Value : %x ===\n", rddsm[0]); | ||||
| 
 | ||||
| 	if (rddsm[0] & 0x80) | ||||
| 		dsim_info("* TE On\n"); | ||||
| 	else | ||||
| 		dsim_info("* TE OFF\n"); | ||||
| 
 | ||||
| 	if (rddsm[0] & 0x02) | ||||
| 		dsim_info("* S_DSI_ERR : Found\n"); | ||||
| 
 | ||||
| 	if (rddsm[0] & 0x01) | ||||
| 		dsim_info("* DSI_ERR : Found\n"); | ||||
| 
 | ||||
| 	ret = dsim_read_from_panel(dsim, S6E3HA2_ID_REG, S6E3HA2_RD_LEN, id); | ||||
| 	if (ret != S6E3HA2_RD_LEN) { | ||||
| 		dsim_err("%s : can't read panel id\n",__func__); | ||||
| 		goto dump_exit; | ||||
| 	} | ||||
| 
 | ||||
| 	ret = dsim_write_by_panel(dsim, SEQ_TEST_KEY_OFF_FC, ARRAY_SIZE(SEQ_TEST_KEY_OFF_FC)); | ||||
| 	if (ret < 0) { | ||||
| 		dsim_err("%s : fail to write CMD : SEQ_TEST_KEY_OFF_FC\n", __func__); | ||||
| 	} | ||||
| 
 | ||||
| 	ret = dsim_write_by_panel(dsim, SEQ_TEST_KEY_OFF_F0, ARRAY_SIZE(SEQ_TEST_KEY_OFF_F0)); | ||||
| 	if (ret < 0) { | ||||
| 		dsim_err("%s : fail to write CMD : SEQ_TEST_KEY_OFF_F0\n", __func__); | ||||
| 	} | ||||
| dump_exit: | ||||
| 	dsim_info(" - %s\n", __func__); | ||||
| 	return ret; | ||||
| 
 | ||||
| } | ||||
| 
 | ||||
| int lcd_dump(int id) | ||||
| { | ||||
| 	s6e3ha2_wqhd_dump(id); | ||||
| 	return 0; | ||||
| } | ||||
							
								
								
									
										213
									
								
								drivers/video/fbdev/exynos/decon_8890/panels/s6e3ha2k_mipi_lcd.c
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										213
									
								
								drivers/video/fbdev/exynos/decon_8890/panels/s6e3ha2k_mipi_lcd.c
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,213 @@ | |||
| /* drivers/video/exynos/decon/panels/s6e3ha2k_mipi_lcd.c
 | ||||
|  * | ||||
|  * Samsung SoC MIPI LCD driver. | ||||
|  * | ||||
|  * Copyright (c) 2014 Samsung Electronics | ||||
|  * | ||||
|  * Haowei Li, <haowei.li@samsung.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. | ||||
| */ | ||||
| 
 | ||||
| #include <linux/delay.h> | ||||
| #include <linux/gpio.h> | ||||
| #include <video/mipi_display.h> | ||||
| #include <linux/platform_device.h> | ||||
| 
 | ||||
| #include "../dsim.h" | ||||
| #include "lcd_ctrl.h" | ||||
| #include "decon_lcd.h" | ||||
| 
 | ||||
| #define MAX_BRIGHTNESS 255 | ||||
| #define MIN_BRIGHTNESS 0 | ||||
| #define DEFAULT_BRIGHTNESS 0 | ||||
| 
 | ||||
| static struct dsim_device *dsim_base; | ||||
| static struct backlight_device *bd; | ||||
| 
 | ||||
| static int s6e3ha2k_get_brightness(struct backlight_device *bd) | ||||
| { | ||||
| 	return bd->props.brightness; | ||||
| } | ||||
| 
 | ||||
| static int get_backlight_level(int brightness) | ||||
| { | ||||
| 	int backlightlevel; | ||||
| 
 | ||||
| 	switch (brightness) { | ||||
| 	case 0: | ||||
| 		backlightlevel = 0; | ||||
| 		break; | ||||
| 	case 1 ... 29: | ||||
| 		backlightlevel = 0; | ||||
| 		break; | ||||
| 	case 30 ... 34: | ||||
| 		backlightlevel = 1; | ||||
| 		break; | ||||
| 	case 35 ... 39: | ||||
| 		backlightlevel = 2; | ||||
| 		break; | ||||
| 	case 40 ... 44: | ||||
| 		backlightlevel = 3; | ||||
| 		break; | ||||
| 	case 45 ... 49: | ||||
| 		backlightlevel = 4; | ||||
| 		break; | ||||
| 	case 50 ... 54: | ||||
| 		backlightlevel = 5; | ||||
| 		break; | ||||
| 	case 55 ... 64: | ||||
| 		backlightlevel = 6; | ||||
| 		break; | ||||
| 	case 65 ... 74: | ||||
| 		backlightlevel = 7; | ||||
| 		break; | ||||
| 	case 75 ... 83: | ||||
| 		backlightlevel = 8; | ||||
| 		break; | ||||
| 	case 84 ... 93: | ||||
| 		backlightlevel = 9; | ||||
| 		break; | ||||
| 	case 94 ... 103: | ||||
| 		backlightlevel = 10; | ||||
| 		break; | ||||
| 	case 104 ... 113: | ||||
| 		backlightlevel = 11; | ||||
| 		break; | ||||
| 	case 114 ... 122: | ||||
| 		backlightlevel = 12; | ||||
| 		break; | ||||
| 	case 123 ... 132: | ||||
| 		backlightlevel = 13; | ||||
| 		break; | ||||
| 	case 133 ... 142: | ||||
| 		backlightlevel = 14; | ||||
| 		break; | ||||
| 	case 143 ... 152: | ||||
| 		backlightlevel = 15; | ||||
| 		break; | ||||
| 	case 153 ... 162: | ||||
| 		backlightlevel = 16; | ||||
| 		break; | ||||
| 	case 163 ... 171: | ||||
| 		backlightlevel = 17; | ||||
| 		break; | ||||
| 	case 172 ... 181: | ||||
| 		backlightlevel = 18; | ||||
| 		break; | ||||
| 	case 182 ... 191: | ||||
| 		backlightlevel = 19; | ||||
| 		break; | ||||
| 	case 192 ... 201: | ||||
| 		backlightlevel = 20; | ||||
| 		break; | ||||
| 	case 202 ... 210: | ||||
| 		backlightlevel = 21; | ||||
| 		break; | ||||
| 	case 211 ... 220: | ||||
| 		backlightlevel = 22; | ||||
| 		break; | ||||
| 	case 221 ... 230: | ||||
| 		backlightlevel = 23; | ||||
| 		break; | ||||
| 	case 231 ... 240: | ||||
| 		backlightlevel = 24; | ||||
| 		break; | ||||
| 	case 241 ... 250: | ||||
| 		backlightlevel = 25; | ||||
| 		break; | ||||
| 	case 251 ... 255: | ||||
| 		backlightlevel = 26; | ||||
| 		break; | ||||
| 	default: | ||||
| 		backlightlevel = 12; | ||||
| 		break; | ||||
| 	} | ||||
| 
 | ||||
| 	return backlightlevel; | ||||
| } | ||||
| 
 | ||||
| static int update_brightness(int brightness) | ||||
| { | ||||
| 	int backlightlevel; | ||||
| 
 | ||||
| 	backlightlevel = get_backlight_level(brightness); | ||||
| 	/* Need to implement
 | ||||
| 	if (s5p_mipi_dsi_wr_data(dsim_base, MIPI_DSI_DCS_LONG_WRITE, | ||||
| 			(unsigned int)gamma22_table[backlightlevel], | ||||
| 				GAMMA_PARAM_SIZE) == -1) | ||||
| 		printk(KERN_ERR "fail to write gamma value.\n"); | ||||
| 
 | ||||
| 	if (s5p_mipi_dsi_wr_data(dsim_base, MIPI_DSI_DCS_SHORT_WRITE_PARAM, | ||||
| 			(unsigned int)0xF7, (unsigned int)0x03) == -1) | ||||
| 		printk(KERN_ERR "fail to update gamma value.\n"); | ||||
| 	*/ | ||||
| 	return 0; | ||||
| } | ||||
| 
 | ||||
| static int s6e3ha2k_set_brightness(struct backlight_device *bd) | ||||
| { | ||||
| 	int brightness = bd->props.brightness; | ||||
| 
 | ||||
| 	if (brightness < MIN_BRIGHTNESS || brightness > MAX_BRIGHTNESS) { | ||||
| 		pr_err("Brightness should be in the range of 0 ~ 255\n"); | ||||
| 		return -EINVAL; | ||||
| 	} | ||||
| 
 | ||||
| 	update_brightness(brightness); | ||||
| 
 | ||||
| 	return 0; | ||||
| } | ||||
| 
 | ||||
| static const struct backlight_ops s6e3ha2k_backlight_ops = { | ||||
| 	.get_brightness = s6e3ha2k_get_brightness, | ||||
| 	.update_status = s6e3ha2k_set_brightness, | ||||
| }; | ||||
| 
 | ||||
| static int s6e3ha2k_probe(struct dsim_device *dsim) | ||||
| { | ||||
| 	dsim_base = dsim; | ||||
| 
 | ||||
| 	bd = backlight_device_register("pwm-backlight.0", NULL, | ||||
| 		NULL, &s6e3ha2k_backlight_ops, NULL); | ||||
| 	if (IS_ERR(bd)) | ||||
| 		pr_err("failed to register backlight device!\n"); | ||||
| 
 | ||||
| 	bd->props.max_brightness = MAX_BRIGHTNESS; | ||||
| 	bd->props.brightness = DEFAULT_BRIGHTNESS; | ||||
| 
 | ||||
| 	return 0; | ||||
| } | ||||
| 
 | ||||
| static int s6e3ha2k_displayon(struct dsim_device *dsim) | ||||
| { | ||||
| 	lcd_init(dsim->id, &dsim->lcd_info); | ||||
| 	lcd_enable(dsim->id); | ||||
| 	return 1; | ||||
| } | ||||
| 
 | ||||
| static int s6e3ha2k_suspend(struct dsim_device *dsim) | ||||
| { | ||||
| 	return 0; | ||||
| } | ||||
| 
 | ||||
| static int s6e3ha2k_resume(struct dsim_device *dsim) | ||||
| { | ||||
| 	return 0; | ||||
| } | ||||
| 
 | ||||
| static int s6e3ha2k_dump(struct dsim_device *dsim) | ||||
| { | ||||
| 	lcd_dump(dsim->id); | ||||
| 	return 0; | ||||
| } | ||||
| 
 | ||||
| struct mipi_dsim_lcd_driver s6e3ha2k_mipi_lcd_driver = { | ||||
| 	.probe		= s6e3ha2k_probe, | ||||
| 	.displayon	= s6e3ha2k_displayon, | ||||
| 	.suspend	= s6e3ha2k_suspend, | ||||
| 	.resume		= s6e3ha2k_resume, | ||||
| 	.dump		= s6e3ha2k_dump, | ||||
| }; | ||||
							
								
								
									
										132
									
								
								drivers/video/fbdev/exynos/decon_8890/panels/s6e3ha2k_param.h
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										132
									
								
								drivers/video/fbdev/exynos/decon_8890/panels/s6e3ha2k_param.h
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,132 @@ | |||
| /* linux/drivers/video/decon_display/s6e3fa0_param.h
 | ||||
|  * | ||||
|  * Copyright (c) 2014 Samsung Electronics Co., Ltd. | ||||
|  * | ||||
|  * Jiun Yu <jiun.yu@samsung.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. | ||||
| */ | ||||
| 
 | ||||
| #ifndef __S6E3HA0K_PARAM_H__ | ||||
| #define __S6E3HA0K_PARAM_H__ | ||||
| 
 | ||||
| #define S6E3HA2_ID_REG			0x04 | ||||
| #define S6E3HA2_RD_LEN			3 | ||||
| #define S6E3HA2_RDDPM_ADDR		0x0A | ||||
| #define S6E3HA2_RDDSM_ADDR		0x0E | ||||
| 
 | ||||
| /* MIPI commands list */ | ||||
| static const unsigned char SEQ_TEST_KEY_ON_F0[] = { | ||||
| 	0xF0, | ||||
| 	0x5A, 0x5A | ||||
| }; | ||||
| 
 | ||||
| static const unsigned char SEQ_TEST_KEY_ON_FC[] = { | ||||
| 	0xFC, | ||||
| 	0x5A, 0x5A | ||||
| }; | ||||
| 
 | ||||
| static const unsigned char SEQ_TEST_KEY_OFF_FC[] = { | ||||
| 	0xFC, | ||||
| 	0xA5, 0xA5 | ||||
| }; | ||||
| 
 | ||||
| static const unsigned char SEQ_SLEEP_OUT[] = { | ||||
| 	0x11, | ||||
| }; | ||||
| 
 | ||||
| static const unsigned char SEQ_REG_F2[] = { | ||||
| 	0xF2, | ||||
| 	0x67, 0x41, 0xC3, 0x06, 0x0A | ||||
| }; | ||||
| 
 | ||||
| static const unsigned char SEQ_TE_START_SETTING[] = { | ||||
| 	0xB9, | ||||
| 	0x10, 0x09, 0xFF, 0x00, 0x09 | ||||
| }; | ||||
| 
 | ||||
| static const unsigned char SEQ_REG_F9[] = { | ||||
| 	0xF9, | ||||
| 	0x29 | ||||
| }; | ||||
| 
 | ||||
| static const unsigned char SEQ_TOUCH_HSYNC[] = { | ||||
| 	0xBD, | ||||
| 	0x30, 0x22, 0x02, 0x16, 0x02, 0x16 | ||||
| }; | ||||
| 
 | ||||
| static const unsigned char SEQ_PENTILE_CONTROL[] = { | ||||
| 	0xC0, | ||||
| 	0x30, 0x00, 0xD8, 0xD8 | ||||
| }; | ||||
| 
 | ||||
| static const unsigned char SEQ_COLUMN_ADDRESS[] = { | ||||
| 	0x2A, | ||||
| 	0x00, 0x00, 0x05, 0x9F | ||||
| }; | ||||
| 
 | ||||
| static const unsigned char SEQ_GAMMA_CONDITION_SET[] = { | ||||
| 	0xCA, | ||||
| 	0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x80, 0x80, 0x80, 0x80, | ||||
| 	0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, | ||||
| 	0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, | ||||
| 	0x80, 0x80, 0x80, 0x00, 0x00 | ||||
| }; | ||||
| 
 | ||||
| static const unsigned char SEQ_AID_SET[] = { | ||||
| 	0xB2, | ||||
| 	0x03, 0x10 | ||||
| }; | ||||
| 
 | ||||
| static const unsigned char SEQ_ELVSS_SET[] = { | ||||
| 	0xB6, | ||||
| 	0x9C, 0x0A | ||||
| }; | ||||
| 
 | ||||
| static const unsigned char SEQ_GAMMA_UPDATE[] = { | ||||
| 	0xF7, | ||||
| 	0x03 | ||||
| }; | ||||
| 
 | ||||
| static const unsigned char SEQ_ACL_OFF[] = { | ||||
| 	0x55, | ||||
| 	0x00 | ||||
| }; | ||||
| 
 | ||||
| static const unsigned char SEQ_ACL_OPR[] = { | ||||
| 	0xB5, | ||||
| 	0x40 | ||||
| }; | ||||
| 
 | ||||
| static const unsigned char SEQ_HBM_OFF[] = { | ||||
| 	0xB4, | ||||
| 	0x04 | ||||
| }; | ||||
| 
 | ||||
| static const unsigned char SEQ_TSET_GLOBAL[] = { | ||||
| 	0xB0, | ||||
| 	0x07 | ||||
| }; | ||||
| 
 | ||||
| static const unsigned char SEQ_TSET[] = { | ||||
| 	0xB8, | ||||
| 	0x19 | ||||
| }; | ||||
| 
 | ||||
| static const unsigned char SEQ_TEST_KEY_OFF_F0[] = { | ||||
| 	0xF0, | ||||
| 	0xA5, 0xA5 | ||||
| }; | ||||
| 
 | ||||
| static const unsigned char SEQ_DISPLAY_ON[] = { | ||||
| 	0x29, | ||||
| }; | ||||
| 
 | ||||
| static const unsigned char SEQ_TE_ON[] = { | ||||
| 	0x35, | ||||
| 	0x00 | ||||
| }; | ||||
| 
 | ||||
| #endif /* __S6E3HA0K_PARAM_H__ */ | ||||
							
								
								
									
										443
									
								
								drivers/video/fbdev/exynos/decon_8890/regs-decon.h
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										443
									
								
								drivers/video/fbdev/exynos/decon_8890/regs-decon.h
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,443 @@ | |||
| /*
 | ||||
|  * drivers/video/exynos_8890/decon/regs-decon.h | ||||
|  * | ||||
|  * Register definition file for Samsung DECON driver | ||||
|  * | ||||
|  * Copyright (c) 2014 Samsung Electronics | ||||
|  * Sewoon Park <seuni.park@samsung.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. | ||||
| */ | ||||
| 
 | ||||
| 
 | ||||
| #ifndef _REGS_DISP_SS_H | ||||
| #define _REGS_DISP_SS_H | ||||
| 
 | ||||
| #define DISP_CFG					0x0000 | ||||
| #define DISP_CFG_DP_PATH_CFG0_EN			(0x1 << 20) | ||||
| #define DISP_CFG_DSIM_PATH_CFG1_DISP_IF_MASK(_v)	(0x3 << (9 + (_v) * 4)) | ||||
| #define DISP_CFG_DSIM_PATH_CFG1_DISP_IF0(_v)		(0x0 << (9 + (_v) * 4)) | ||||
| #define DISP_CFG_DSIM_PATH_CFG1_DISP_IF1(_v)		(0x1 << (9 + (_v) * 4)) | ||||
| #define DISP_CFG_DSIM_PATH_CFG1_DISP_IF2(_v)		(0x2 << (9 + (_v) * 4)) | ||||
| #define DISP_CFG_DSIM_PATH_CFG0_EN(_v)			(0x1 << (8 + (_v) * 4)) | ||||
| #define DISP_CFG_DSIM_PATH_CFG0_MASK(_v)		(0x1 << (8 + (_v) * 4)) | ||||
| #define DISP_CFG_SYNC_MODE1_TE(_v)			((_v) << 2) | ||||
| #define DISP_CFG_SYNC_MODE1_MASK			(0x3 << 2) | ||||
| #define DISP_CFG_SYNC_MODE0_TE(_v)			((_v) << 0) | ||||
| #define DISP_CFG_SYNC_MODE0_MASK			(0x3 << 0) | ||||
| 
 | ||||
| #define DISP_CFG_SYNC_MODE1_TE_F			(0x0 << 2) | ||||
| #define DISP_CFG_SYNC_MODE1_TE_S			(0x1 << 2) | ||||
| #define DISP_CFG_SYNC_MODE1_TE_T			(0x2 << 2) | ||||
| #define DISP_CFG_SYNC_MODE1_MASK			(0x3 << 2) | ||||
| #define DISP_CFG_SYNC_MODE0_TE_F			(0x0 << 0) | ||||
| #define DISP_CFG_SYNC_MODE0_TE_S			(0x1 << 0) | ||||
| #define DISP_CFG_SYNC_MODE0_TE_T			(0x2 << 0) | ||||
| #define DISP_CFG_SYNC_MODE0_MASK			(0x3 << 0) | ||||
| 
 | ||||
| #endif /* _REGS_DISP_SS_H */ | ||||
| 
 | ||||
| 
 | ||||
| #ifndef _REGS_DECON_H | ||||
| #define _REGS_DECON_H | ||||
| 
 | ||||
| /*
 | ||||
|  *	IP			start_offset	end_offset | ||||
|  *================================================= | ||||
|  *	DECON_F			0x0000		0x007f | ||||
|  *	DECON_F/DISPIF0,1	0x0080		0x00F4 | ||||
|  *	DECON_F			0x00F8		0x0FFF | ||||
|  *------------------------------------------------- | ||||
|  *	MIC			0x1000		0x1FFF | ||||
|  *------------------------------------------------- | ||||
|  *	DSC_ENC0		0x2000		0x2FFF | ||||
|  *	DSC_ENC1		0x3000		0x3FFF | ||||
|  *------------------------------------------------- | ||||
|  *	DECON_S/DISPIF2		0x5000		0x5FFF | ||||
|  *	DECON_T/DISPIF3		0x6000		0x6FFF | ||||
|  *------------------------------------------------- | ||||
|  *------------------------------------------------- | ||||
|  *	SHD_DECON_F		0x7000		0x7FFF | ||||
|  *------------------------------------------------- | ||||
|  *	SHD_MIC			0x8000		0x8FFF | ||||
|  *------------------------------------------------- | ||||
|  *	SHD_DSC_ENC0		0x9000		0x9FFF | ||||
|  *	SHD_DSC_ENC1		0xA000		0xAFFF | ||||
|  *------------------------------------------------- | ||||
|  *	SHD_DISPIF2		0xB000		0xBFFF | ||||
|  *	SHD_DISPIF3		0xC000		0xCFFF | ||||
|  *------------------------------------------------- | ||||
|  *	mDNIe			0xD000		0xDFFF | ||||
|  *------------------------------------------------- | ||||
|  *	DPU			0xE000		0xFFFF | ||||
| */ | ||||
| 
 | ||||
| 
 | ||||
| /*
 | ||||
|  * DECON_F registers | ||||
|  * -> | ||||
|  * updated by SHADOW_REG_UPDATE_REQ[31] : SHADOW_REG_UPDATE_REQ | ||||
|  *	(0x0000~0x011C, 0x0230~0x209C, Dither/MIC/DSC) | ||||
| */ | ||||
| 
 | ||||
| #define GLOBAL_CONTROL					0x0000 | ||||
| #define GLOBAL_CONTROL_SRESET				(1 << 28) | ||||
| #define GLOBAL_CONTROL_AUTOMATIC_MAPCOLOR_ENTER_EN_F	(1 << 12) | ||||
| #define GLOBAL_CONTROL_OPERATION_MODE_F			(1 << 8) | ||||
| #define GLOBAL_CONTROL_OPERATION_MODE_RGBIF_F		(0 << 8) | ||||
| #define GLOBAL_CONTROL_OPERATION_MODE_I80IF_F		(1 << 8) | ||||
| #define GLOBAL_CONTROL_URGENT_STATUS			(1 << 6) | ||||
| #define GLOBAL_CONTROL_IDLE_STATUS			(1 << 5) | ||||
| #define GLOBAL_CONTROL_RUN_STATUS			(1 << 4) | ||||
| #define GLOBAL_CONTROL_DECON_EN				(1 << 1) | ||||
| #define GLOBAL_CONTROL_DECON_EN_F			(1 << 0) | ||||
| 
 | ||||
| #define AUTOMATIC_MAPCOLOR_PERIOD_CONTROL		0x0004 | ||||
| #define AUTOMATIC_MAPCOLOR_PERIOD_F(_v)			((_v) << 0) | ||||
| 
 | ||||
| #define RESOURCE_OCCUPANCY_INFO_0			0x0010 | ||||
| #define RESOURCE_OCCUPANCY_INFO_1			0x0014 | ||||
| #define RESOURCE_SEL_0					0x0018/* DECon_F only */ | ||||
| #define RESOURCE_SEL_1					0x001C/* DECon_F only */ | ||||
| #define RESOURCE_CONFLICTION_INDUCER			0x0020 | ||||
| 
 | ||||
| #define SRAM_SHARE_ENABLE				0x0030/* DECon_F only */ | ||||
| #define SRAM_SHARE_ENABLE_DSC_F				(1 << 4) | ||||
| #define SRAM_SHARE_ENABLE_F				(1 << 0) | ||||
| 
 | ||||
| #define INTERRUPT_ENABLE				0x0040 | ||||
| #define INTERRUPT_DPU1_INT_EN				(1 << 29) | ||||
| #define INTERRUPT_DPU0_INT_EN				(1 << 28) | ||||
| #define INTERRUPT_DISPIF_VSTATUS_INT_EN			(1 << 24) | ||||
| #define INTERRUPT_DISPIF_VSTATUS_VBP			(0 << 20) | ||||
| #define INTERRUPT_DISPIF_VSTATUS_VSA			(1 << 20) | ||||
| #define INTERRUPT_DISPIF_VSTATUS_VACTIVE		(2 << 20) | ||||
| #define INTERRUPT_DISPIF_VSTATUS_VFP			(3 << 20) | ||||
| #define INTERRUPT_RESOURCE_CONFLICT_INT_EN		(1 << 18) | ||||
| #define INTERRUPT_EVEN_FRAME_START_INT_EN		(1 << 17) | ||||
| #define INTERRUPT_ODD_FRAME_START_INT_EN		(1 << 16) | ||||
| #define INTERRUPT_FRAME_DONE_INT_EN			(1 << 12) | ||||
| #define INTERRUPT_FIFO_LEVEL_INT_EN			(1 << 8) | ||||
| #define INTERRUPT_INT_EN				(1 << 0) | ||||
| 
 | ||||
| #define UNDER_RUN_CYCLE_THRESHOLD			0x0044 | ||||
| #define INTERRUPT_PENDING				0x0048 | ||||
| 
 | ||||
| #define SHADOW_REG_UPDATE_REQ				0x0060 | ||||
| #define SHADOW_REG_UPDATE_REQ_GLOBAL			(1 << 31) | ||||
| #define SHADOW_REG_UPDATE_REQ_DPU			(1 << 28) | ||||
| #define SHADOW_REG_UPDATE_REQ_MDNIE			(1 << 24) | ||||
| #define SHADOW_REG_UPDATE_REQ_WIN(_win)			(1 << (_win)) | ||||
| #define SHADOW_REG_UPDATE_REQ_FOR_DECON_F		(0xff) | ||||
| #define SHADOW_REG_UPDATE_REQ_FOR_DECON_T		(0xf) | ||||
| 
 | ||||
| #define HW_SW_TRIG_CONTROL				0x0070 | ||||
| #define HW_SW_TRIG_CONTROL_TRIG_AUTO_MASK_TRIG		(1 << 12) | ||||
| /* 1 : s/w trigger */ | ||||
| #define HW_SW_TRIG_CONTROL_SW_TRIG			(1 << 8) | ||||
| /* 0 : unmask, 1 : mask */ | ||||
| #define HW_SW_TRIG_CONTROL_HW_TRIG_MASK			(1 << 5) | ||||
| /* 0 : s/w trigger, 1 : h/w trigger */ | ||||
| #define HW_SW_TRIG_CONTROL_HW_TRIG_EN			(1 << 4) | ||||
| 
 | ||||
| #define DISPIF0_DISPIF1_CONTROL				0x0080/* DECon_F only */ | ||||
| #define DISPIF0_DISPIF1_CONTROL_FREE_RUN_EN		(1 << 4) | ||||
| #define DISPIF0_DISPIF1_CONTROL_UNDERRUN_SCHEME_F(_v)	((_v) << 12) | ||||
| #define DISPIF0_DISPIF1_CONTROL_UNDERRUN_SCHEME_MASK	(0x3 << 12) | ||||
| #define DISPIF0_DISPIF1_CONTROL_OUT_RGB_ORDER_F(_v)	((_v) << 8) | ||||
| #define DISPIF0_DISPIF1_CONTROL_OUT_RGB_ORDER_MASK	(0x7 << 8) | ||||
| 
 | ||||
| #define DISPIF0_MAPCOLOR				0x0084/* DECon_F only */ | ||||
| #define DISPIF1_MAPCOLOR				0x0088/* DECon_F only */ | ||||
| 
 | ||||
| #define DISPIF_LINE_COUNT				0x008C/* DECon_F only */ | ||||
| #define DISPIF_LINE_COUNT_DISPIF1_SHIFT			16 | ||||
| #define DISPIF_LINE_COUNT_DISPIF1_MASK			(0xffff << 16) | ||||
| #define DISPIF_LINE_COUNT_DISPIF0_SHIFT			0 | ||||
| #define DISPIF_LINE_COUNT_DISPIF0_MASK			(0xffff << 0) | ||||
| 
 | ||||
| #define DISPIF0_TIMING_CONTROL_0			0x0090/* DECon_F only */ | ||||
| #define DISPIF_TIMING_VBPD_F(_v)			((_v) << 16) | ||||
| #define DISPIF_TIMING_VFPD_F(_v)			((_v) << 0) | ||||
| 
 | ||||
| #define DISPIF0_TIMING_CONTROL_1			0x0094/* DECon_F only */ | ||||
| #define DISPIF_TIMING_VSPD_F(_v)			((_v) << 0) | ||||
| 
 | ||||
| #define DISPIF0_TIMING_CONTROL_2			0x0098/* DECon_F only */ | ||||
| #define DISPIF_TIMING_HBPD_F(_v)			((_v) << 16) | ||||
| #define DISPIF_TIMING_HFPD_F(_v)			((_v) << 0) | ||||
| 
 | ||||
| #define DISPIF0_TIMING_CONTROL_3			0x009C/* DECon_F only */ | ||||
| #define DISPIF_TIMING_HSPD_F(_v)			((_v) << 0) | ||||
| 
 | ||||
| #define DISPIF0_SIZE_CONTROL_0				0x00A0/* DECon_F only */ | ||||
| #define DISPIF_HEIGHT_F(_v)				((_v) << 16) | ||||
| #define DISPIF_HEIGHT_MASK				(0x3fff << 16) | ||||
| #define DISPIF_HEIGHT_GET(_v)				(((_v) >> 16) & 0x3fff) | ||||
| #define DISPIF_WIDTH_F(_v)				((_v) << 0) | ||||
| #define DISPIF_WIDTH_MASK				(0x3fff << 0) | ||||
| #define DISPIF_WIDTH_GET(_v)				(((_v) >> 0) & 0x3fff) | ||||
| 
 | ||||
| /* All of DECON */ | ||||
| /* DISP INTERFACE OFFSET : IF0,1 = 0x0, IF2 = 0x5000, IF3 = 0x6000 */ | ||||
| #define IF_OFFSET(_x)			((((_x) < 2) ? 0 : 0x1000) * ((_x) + 3)) | ||||
| /* For TIMING VALUE : IF0,2,3 = 0x0, IF1 = 0x30 */ | ||||
| #define IF1_OFFSET(_x)			(((_x) == 1) ? 0x30 : 0x0) | ||||
| #define DISPIF_SIZE_CONTROL_0(_if_idx) \ | ||||
| 	(0x00A0 + IF_OFFSET(_if_idx) + IF1_OFFSET(_if_idx)) | ||||
| #define DISPIF_WIDTH_START_POS				(0) | ||||
| #define DISPIF_HEIGHT_START_POS				(16) | ||||
| 
 | ||||
| #define DISPIF0_SIZE_CONTROL_1				0x00A4/* DECon_F only */ | ||||
| #define DISPIF0_URGENT_CONTROL				0x00A8/* DECon_F only */ | ||||
| #define DISPIF1_TIMING_CONTROL_0			0x00C0/* DECon_F only */ | ||||
| #define DISPIF1_TIMING_CONTROL_1			0x00C4/* DECon_F only */ | ||||
| #define DISPIF1_TIMING_CONTROL_2			0x00C8/* DECon_F only */ | ||||
| #define DISPIF1_TIMING_CONTROL_3			0x00CC/* DECon_F only */ | ||||
| #define DISPIF1_SIZE_CONTROL_0				0x00D0/* DECon_F only */ | ||||
| #define DISPIF1_SIZE_CONTROL_1				0x00D4/* DECon_F only */ | ||||
| #define DISPIF1_URGENT_CONTROL				0x00D8/* DECon_F only */ | ||||
| 
 | ||||
| #define CLOCK_CONTROL_0					0x00F0 | ||||
| /* [16] 0: QACTIVE is dynamically changed by DECON h/w,
 | ||||
|  * 1: QACTIVE is stuck to 1'b1 | ||||
| */ | ||||
| #define CLOCK_CONTROL_0_F_MASK				(0xF31000FF) | ||||
| #define CLOCK_CONTROL_0_S_MASK				(0x1300FF0F) | ||||
| #define CLOCK_CONTROL_0_T_MASK				(0x1300FF0F) | ||||
| 
 | ||||
| #define VCLK_DIVIDER_CONTROL				0x00F4/* DECon_F only */ | ||||
| #define ECLK_DIVIDER_CONTROL				0x00F8 | ||||
| 
 | ||||
| #define BLENDER_BG_IMAGE_SIZE_0				0x0110 | ||||
| #define BLENDER_BG_HEIGHT_F(_v)				((_v) << 16) | ||||
| #define BLENDER_BG_HEIGHT_MASK				(0x3fff << 16) | ||||
| #define BLENDER_BG_HEIGHT_GET(_v)			(((_v) >> 16) & 0x3fff) | ||||
| #define BLENDER_BG_WIDTH_F(_v)				((_v) << 0) | ||||
| #define BLENDER_BG_WIDTH_MASK				(0x3fff << 0) | ||||
| #define BLENDER_BG_WIDTH_GET(_v)			(((_v) >> 0) & 0x3fff) | ||||
| 
 | ||||
| #define BLENDER_BG_IMAGE_SIZE_1				0x0114 | ||||
| #define BLENDER_BG_IMAGE_COLOR				0x0118 | ||||
| 
 | ||||
| #define LRMERGER_MODE_CONTROL				0x011C | ||||
| 
 | ||||
| #define WIN_CONTROL(_win)			(0x0130 + ((_win) * 0x20)) | ||||
| #define WIN_CONTROL_ALPHA1_F(_v)		(((_v) & 0xFF) << 24) | ||||
| #define WIN_CONTROL_ALPHA1_MASK			(0xFF << 24) | ||||
| #define WIN_CONTROL_ALPHA0_F(_v)		(((_v) & 0xFF) << 16) | ||||
| #define WIN_CONTROL_ALPHA0_MASK			(0xFF << 16) | ||||
| #define WIN_CONTROL_CHMAP_F(_v)			(((_v) & 0x7) << 12) | ||||
| #define WIN_CONTROL_CHMAP_MASK			(0x7 << 12) | ||||
| #define WIN_CONTROL_FUNC_F(_v)			(((_v) & 0xF) << 8) | ||||
| #define WIN_CONTROL_FUNC_MASK			(0xF << 8) | ||||
| #define WIN_CONTROL_ALPHA_MUL_F			(1 << 6) | ||||
| #define WIN_CONTROL_ALPHA_SEL_F(_v)		(((_v) & 0x7) << 4) | ||||
| #define WIN_CONTROL_ALPHA_SEL_MASK		(0x7 << 4) | ||||
| #define WIN_CONTROL_MAPCOLOR_EN_F		(1 << 1) | ||||
| #define WIN_CONTROL_MAPCOLOR_EN_MASK		(1 << 1) | ||||
| #define WIN_CONTROL_EN_F			(1 << 0) | ||||
| 
 | ||||
| #define WIN_START_POSITION(_win)		(0x0134 + ((_win) * 0x20)) | ||||
| #define WIN_STRPTR_Y_F(_v)			(((_v) & 0x1FFF) << 16) | ||||
| #define WIN_STRPTR_X_F(_v)			(((_v) & 0x1FFF) << 0) | ||||
| 
 | ||||
| #define WIN_END_POSITION(_win)			(0x0138 + ((_win) * 0x20)) | ||||
| #define WIN_ENDPTR_Y_F(_v)			(((_v) & 0x1FFF) << 16) | ||||
| #define WIN_ENDPTR_X_F(_v)			(((_v) & 0x1FFF) << 0) | ||||
| 
 | ||||
| #define WIN_COLORMAP(_win)			(0x013C + ((_win) * 0x20)) | ||||
| #define WIN_COLORMAP_MAPCOLOR_F(_v)		((_v) << 0) | ||||
| #define WIN_COLORMAP_MAPCOLOR_MASK		(0xffffff << 0) | ||||
| 
 | ||||
| #define WIN_START_TIME_CONTROL(_win)		(0x0140 + ((_win) * 0x20)) | ||||
| 
 | ||||
| #define WIN_PIXEL_COUNT(_win)			(0x0144 + ((_win) * 0x20)) | ||||
| 
 | ||||
| #define DATA_PATH_CONTROL				0x0230 | ||||
| #define DATA_PATH_CONTROL_ENHANCE_SHIFT			8 | ||||
| #define DATA_PATH_CONTROL_ENHANCE_MASK			(0x7 << 8) | ||||
| #define DATA_PATH_CONTROL_ENHANCE(_v)			((_v) << 8) | ||||
| #define DATA_PATH_CONTROL_ENHANCE_GET(_v)		(((_v) >> 8) & 0x7) | ||||
| #define DATA_PATH_CONTROL_PATH_SHIFT			0 | ||||
| #define DATA_PATH_CONTROL_PATH_MASK			(0xFF << 0) | ||||
| #define DATA_PATH_CONTROL_PATH(_v)			((_v) << 0) | ||||
| #define DATA_PATH_CONTROL_PATH_GET(_v)			(((_v) >> 0) & 0xFF) | ||||
| 
 | ||||
| #define SPLITTER_CONTROL_0				0x0240/* DECon_F only */ | ||||
| 
 | ||||
| #define SPLITTER_SIZE_CONTROL_0				0x0244/* DECon_F only */ | ||||
| #define SPLITTER_HEIGHT_F(_v)				((_v) << 16) | ||||
| #define SPLITTER_HEIGHT_MASK				(0x3fff << 16) | ||||
| #define SPLITTER_WIDTH_F(_v)				((_v) << 0) | ||||
| #define SPLITTER_WIDTH_MASK				(0x3fff << 0) | ||||
| 
 | ||||
| #define SPLITTER_SIZE_CONTROL_1				0x0248/* DECon_F only */ | ||||
| 
 | ||||
| #define FRAME_FIFO_CONTROL				0x024C | ||||
| 
 | ||||
| #define FRAME_FIFO_0_SIZE_CONTROL_0			0x0250 | ||||
| #define FRAME_FIFO_HEIGHT_F(_v)				((_v) << 16) | ||||
| #define FRAME_FIFO_HEIGHT_MASK				(0x3fff << 16) | ||||
| #define FRAME_FIFO_WIDTH_F(_v)				((_v) << 0) | ||||
| #define FRAME_FIFO_WIDTH_MASK				(0x3fff << 0) | ||||
| 
 | ||||
| #define FRAME_FIFO_0_SIZE_CONTROL_1			0x0254 | ||||
| #define FRAME_FIFO_1_SIZE_CONTROL_0			0x0258/* DECon_F only */ | ||||
| #define FRAME_FIFO_1_SIZE_CONTROL_1			0x025C/* DECon_F only */ | ||||
| #define FRAME_FIFO_INFO_0				0x0260 | ||||
| #define FRAME_FIFO_INFO_1				0x0264 | ||||
| #define FRAME_FIFO_INFO_2				0x0268 | ||||
| #define FRAME_FIFO_INFO_3				0x026C | ||||
| 
 | ||||
| #define SRAM_SHARE_COMP_INFO				0x0270/* DECon_F only */ | ||||
| #define SRAM_SHARE_ENH_INFO				0x0274/* DECon_F only */ | ||||
| 
 | ||||
| #define CRC_DATA_0					0x0280 | ||||
| #define CRC_DATA_2					0x0284/* DECon_F only */ | ||||
| #define CRC_CONTROL					0x0288 | ||||
| 
 | ||||
| #define FRAME_ID					0x02A0 | ||||
| 
 | ||||
| #define DEBUG_CLOCK_OUT_SEL				0x02AC | ||||
| 
 | ||||
| #define DITHER_CONTROL					0x0300/* DECon_F only */ | ||||
| 
 | ||||
| 
 | ||||
| /*
 | ||||
| * MIC registers | ||||
| * -> | ||||
| * 0x1004 ~ | ||||
| * updated by SHADOW_REG_UPDATE_REQ[31] : SHADOW_REG_UPDATE_REQ | ||||
| */ | ||||
| 
 | ||||
| #define MIC_CONTROL					0x1004 | ||||
| #define MIC_DUMMY_F(_v)					((_v) << 20) | ||||
| #define MIC_DUMMY_MASK					(0x1ff << 20) | ||||
| /* 0 : single slice, 1: dual slice */ | ||||
| #define MIC_SLICE_NUM_F(_v)				((_v) << 8) | ||||
| #define MIC_SLICE_NUM_MASK				(0x3 << 8) | ||||
| /* 0 : {PIX0, PIX1}, 1 : {PIX1, PIX0} */ | ||||
| #define MIC_PIXEL_ORDER_F(_v)				((_v) << 4) | ||||
| #define MIC_PIXEL_ORDER_MASK				(1 << 4) | ||||
| /* 0 : 1/2, 1: 1/3 */ | ||||
| #define MIC_PARA_CR_CTRL_F(_v)				((_v) << 1) | ||||
| #define MIC_PARA_CR_CTRL_MASK				(1 << 1) | ||||
| #define MIC_PARA_CR_CTRL_SHIFT				1 | ||||
| 
 | ||||
| #define MIC_ENC_PARAM0					0x1008 | ||||
| #define MIC_ENC_PARAM1					0x100C | ||||
| #define MIC_ENC_PARAM2					0x1010 | ||||
| #define MIC_ENC_PARAM3					0x1014 | ||||
| #define MIC_BG_COLOR					0x1018 | ||||
| #define MIC_SIZE_CONTROL				0x101C | ||||
| #define MIC_WIDTH_C_F(_v)				((_v) << 0) | ||||
| #define MIC_WIDTH_C_MASK				(0x3fff << 0) | ||||
| 
 | ||||
| /*
 | ||||
| * <- | ||||
| * MIC registers | ||||
| */ | ||||
| 
 | ||||
| 
 | ||||
| /*
 | ||||
| * DSC registers | ||||
| * -> | ||||
| * 0x2000 ~ | ||||
| * updated by SHADOW_REG_UPDATE_REQ[31] : SHADOW_REG_UPDATE_REQ | ||||
| * | ||||
| * @ regs-dsc.h | ||||
| * | ||||
| * <- | ||||
| * DSC registers | ||||
| */ | ||||
| 
 | ||||
| 
 | ||||
| /*
 | ||||
| * DISPIF2,3 registers | ||||
| * -> | ||||
| */ | ||||
| 
 | ||||
| #define DISPIF2_CONTROL					0x5080/* DECon_F only */ | ||||
| #define DISPIF2_CONTROL_FREE_RUN_EN			(1 << 4) | ||||
| #define DISPIF2_CONTROL_UNDERRUN_SCHEME_F(_v)		((_v) << 12) | ||||
| #define DISPIF2_CONTROL_UNDERRUN_SCHEME_MASK		(0x3 << 12) | ||||
| #define DISPIF2_CONTROL_OUT_RGB_ORDER_F(_v)		((_v) << 8) | ||||
| #define DISPIF2_CONTROL_OUT_RGB_ORDER_MASK		(0x7 << 8) | ||||
| 
 | ||||
| #define DISPIF2_MAPCOLOR				0x5084/* DECon_F only */ | ||||
| 
 | ||||
| #define DISPIF2_LINE_COUNT				0x508C | ||||
| #define DISPIF2_LINE_COUNT_SHIFT			0 | ||||
| #define DISPIF2_LINE_COUNT_MASK				(0xffff << 0) | ||||
| 
 | ||||
| #define DISPIF2_TIMING_CONTROL_0			0x5090/* DECon_F only */ | ||||
| #define DISPIF2_TIMING_CONTROL_1			0x5094/* DECon_F only */ | ||||
| #define DISPIF2_TIMING_CONTROL_2			0x5098/* DECon_F only */ | ||||
| #define DISPIF2_TIMING_CONTROL_3			0x509C/* DECon_F only */ | ||||
| #define DISPIF2_SIZE_CONTROL_0				0x50A0/* DECon_F only */ | ||||
| #define DISPIF2_SIZE_CONTROL_1				0x50A4/* DECon_F only */ | ||||
| 
 | ||||
| #define VCLK2_DIVIDER_CONTROL				0x50F4/* DECon_F only */ | ||||
| 
 | ||||
| #define DISPIF3_CONTROL					0x6080/* DECon_F only */ | ||||
| #define DISPIF3_CONTROL_FREE_RUN_EN			(1 << 4) | ||||
| #define DISPIF3_CONTROL_UNDERRUN_SCHEME_F(_v)		((_v) << 12) | ||||
| #define DISPIF3_CONTROL_UNDERRUN_SCHEME_MASK		(0x3 << 12) | ||||
| #define DISPIF3_CONTROL_OUT_RGB_ORDER_F(_v)		((_v) << 8) | ||||
| #define DISPIF3_CONTROL_OUT_RGB_ORDER_MASK		(0x7 << 8) | ||||
| 
 | ||||
| #define DISPIF3_MAPCOLOR				0x6084/* DECon_F only */ | ||||
| 
 | ||||
| #define DISPIF3_LINE_COUNT				0x608C/* DECon_F only */ | ||||
| #define DISPIF3_LINE_COUNT_SHIFT			0 | ||||
| #define DISPIF3_LINE_COUNT_MASK				(0xffff << 0) | ||||
| 
 | ||||
| #define DISPIF3_TIMING_CONTROL_0			0x6090/* DECon_F only */ | ||||
| #define DISPIF3_TIMING_CONTROL_1			0x6094/* DECon_F only */ | ||||
| 
 | ||||
| #define DISPIF3_TIMING_CONTROL_2			0x6098/* DECon_F only */ | ||||
| #define DISPIF3_TIMING_CONTROL_3			0x609C/* DECon_F only */ | ||||
| 
 | ||||
| #define DISPIF3_SIZE_CONTROL_0				0x60A0/* DECon_F only */ | ||||
| #define DISPIF3_SIZE_CONTROL_1				0x60A4/* DECon_F only */ | ||||
| 
 | ||||
| #define VCLK3_DIVIDER_CONTROL				0x60F4/* DECon_F only */ | ||||
| #define DIVIDER_DENOM_VALUE_OF_CLK_F(_v)		((_v) << 16) | ||||
| #define DIVIDER_NUM_VALUE_OF_CLK_F(_v)			((_v) << 0) | ||||
| 
 | ||||
| /* <-
 | ||||
| * DISPIF2,3 registers | ||||
| */ | ||||
| 
 | ||||
| 
 | ||||
| /*
 | ||||
| * mDNIe registers | ||||
| * -> | ||||
| * 0xD000 ~ | ||||
| *  updated by SHADOW_REG_UPDATE_REQ[24] : SHADOW_REG_UPDATE_REQ_mDNIe | ||||
| * | ||||
| * @ regs-mdnie.h | ||||
| * | ||||
| * <- | ||||
| * mDNIe registers | ||||
| */ | ||||
| 
 | ||||
| 
 | ||||
| /*
 | ||||
| * DPU registers | ||||
| * -> | ||||
| * 0xE000 ~ | ||||
| *  updated by SHADOW_REG_UPDATE_REQ[28] : SHADOW_REG_UPDATE_REQ_DPU | ||||
| * | ||||
| * @ regs-dpu.h | ||||
| * | ||||
| * <- | ||||
| * DPU registers | ||||
| */ | ||||
| 
 | ||||
| #define SHADOW_OFFSET					0x7000 | ||||
| 
 | ||||
| #endif /* _REGS_DECON_H */ | ||||
							
								
								
									
										303
									
								
								drivers/video/fbdev/exynos/decon_8890/regs-dsim.h
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										303
									
								
								drivers/video/fbdev/exynos/decon_8890/regs-dsim.h
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,303 @@ | |||
| /* regs-dsim.h
 | ||||
|  * | ||||
|  * Register definition file for Samsung MIPI-DSIM driver | ||||
|  * | ||||
|  * Copyright (c) 2015 Samsung Electronics | ||||
|  * Jiun Yu <jiun.yu@samsung.com> | ||||
|  * Seuni Park <seuni.park@samsung.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. | ||||
| */ | ||||
| 
 | ||||
| #ifndef _REGS_DSIM_H | ||||
| #define _REGS_DSIM_H | ||||
| 
 | ||||
| #define DSIM_LINK_STATUS			(0x4) | ||||
| #define DSIM_STATUS_PLL_STABLE			(1 << 24) | ||||
| 
 | ||||
| #define DSIM_DPHY_STATUS			(0x8) | ||||
| #define DSIM_STATUS_STOP_STATE_DAT(_x)		(((_x) & 0xf) << 0) | ||||
| #define DSIM_STATUS_ULPS_DAT(_x)		(((_x) & 0xf) << 4) | ||||
| #define DSIM_STATUS_STOP_STATE_CLK		(1 << 8) | ||||
| #define DSIM_STATUS_ULPS_CLK			(1 << 9) | ||||
| #define DSIM_STATUS_TX_READY_HS_CLK		(1 << 10) | ||||
| #define DSIM_STATUS_ULPS_DATA_LANE_GET(x)	(((x) >> 4) & 0xf) | ||||
| 
 | ||||
| #define DSIM_SWRST				(0xc) | ||||
| #define DSIM_SWRST_FUNCRST			(1 << 16) | ||||
| #define DSIM_DPHY_RST				(1 << 8) | ||||
| #define DSIM_SWRST_RESET			(1 << 0) | ||||
| 
 | ||||
| #define DSIM_CLKCTRL				(0x10) | ||||
| #define DSIM_CLKCTRL_TX_REQUEST_HSCLK		(1 << 20) | ||||
| #define DSIM_CLKCTRL_BYTECLK_EN			(1 << 17) | ||||
| #define DSIM_CLKCTRL_ESCCLK_EN			(1 << 16) | ||||
| #define DSIM_CLKCTRL_LANE_ESCCLK_EN_MASK	(0x1f << 8) | ||||
| #define DSIM_CLKCTRL_LANE_ESCCLK_EN(_x)		((_x) << 8) | ||||
| #define DSIM_CLKCTRL_ESC_PRESCALER(_x)		((_x) << 0) | ||||
| #define DSIM_CLKCTRL_ESC_PRESCALER_MASK		(0xffff << 0) | ||||
| 
 | ||||
| /* Time out register */ | ||||
| #define DSIM_TIMEOUT0				(0x14) | ||||
| #define DSIM_TIMEOUT_BTA_TOUT(_x)		((_x) << 16) | ||||
| #define DSIM_TIMEOUT_BTA_TOUT_MASK		(0xff << 16) | ||||
| #define DSIM_TIMEOUT_LPDR_TOUT(_x)		((_x) << 0) | ||||
| #define DSIM_TIMEOUT_LPDR_TOUT_MASK		(0xffff << 0) | ||||
| 
 | ||||
| /* Time out register */ | ||||
| #define DSIM_TIMEOUT1				(0x18) | ||||
| #define DSIM_TIMEOUT_HSYNC_TOUT(_x)		((_x) << 0) | ||||
| #define DSIM_TIMEOUT_HSYNC_TOUT_MASK		(0xff << 0) | ||||
| 
 | ||||
| /* Escape mode register */ | ||||
| #define DSIM_ESCMODE				(0x1c) | ||||
| #define DSIM_ESCMODE_STOP_STATE_CNT(_x)		((_x) << 21) | ||||
| #define DSIM_ESCMODE_STOP_STATE_CNT_MASK	(0x7ff << 21) | ||||
| #define DSIM_ESCMODE_FORCE_STOP_STATE		(1 << 20) | ||||
| #define DSIM_ESCMODE_FORCE_BTA			(1 << 16) | ||||
| #define DSIM_ESCMODE_CMD_LPDT			(1 << 7) | ||||
| #define DSIM_ESCMODE_TRIGGER_RST		(1 << 4) | ||||
| #define DSIM_ESCMODE_TX_ULPS_DATA		(1 << 3) | ||||
| #define DSIM_ESCMODE_TX_ULPS_DATA_EXIT		(1 << 2) | ||||
| #define DSIM_ESCMODE_TX_ULPS_CLK		(1 << 1) | ||||
| #define DSIM_ESCMODE_TX_ULPS_CLK_EXIT		(1 << 0) | ||||
| 
 | ||||
| /* Display image resolution register */ | ||||
| #define DSIM_RESOL				(0x20) | ||||
| #define DSIM_RESOL_VRESOL(x)			(((x) & 0xfff) << 16) | ||||
| #define DSIM_RESOL_VRESOL_MASK			(0xfff << 16) | ||||
| #define DSIM_RESOL_HRESOL(x)			(((x) & 0Xfff) << 0) | ||||
| #define DSIM_RESOL_HRESOL_MASK			(0xfff << 0) | ||||
| #define DSIM_RESOL_LINEVAL_GET(_v)		(((_v) >> 16) & 0xfff) | ||||
| #define DSIM_RESOL_HOZVAL_GET(_v)		(((_v) >> 0) & 0xfff) | ||||
| 
 | ||||
| /* Main display Vporch register */ | ||||
| #define DSIM_VPORCH				(0x24) | ||||
| #define DSIM_VPORCH_CMD_ALLOW(_x)		((_x) << 28) | ||||
| #define DSIM_VPORCH_CMD_ALLOW_MASK		(0xf << 28) | ||||
| #define DSIM_VPORCH_STABLE_VFP(_x)		((_x) << 16) | ||||
| #define DSIM_VPORCH_STABLE_VFP_MASK		(0x7ff << 16) | ||||
| #define DSIM_VPORCH_VBP(_x)			((_x) << 0) | ||||
| #define DSIM_VPORCH_VBP_MASK			(0x7ff << 0) | ||||
| 
 | ||||
| /* Main display Hporch register */ | ||||
| #define DSIM_HPORCH				(0x28) | ||||
| #define DSIM_HPORCH_HFP(_x)			((_x) << 16) | ||||
| #define DSIM_HPORCH_HFP_MASK			(0xffff << 16) | ||||
| #define DSIM_HPORCH_HBP(_x)			((_x) << 0) | ||||
| #define DSIM_HPORCH_HBP_MASK			(0xffff << 0) | ||||
| 
 | ||||
| /* Main display sync area register */ | ||||
| #define DSIM_SYNC				(0x2C) | ||||
| #define DSIM_SYNC_VSA(_x)			((_x) << 16) | ||||
| #define DSIM_SYNC_VSA_MASK			(0x7ff << 16) | ||||
| #define DSIM_SYNC_HSA(_x)			((_x) << 0) | ||||
| #define DSIM_SYNC_HSA_MASK			(0xffff << 0) | ||||
| 
 | ||||
| /* Configuration register */ | ||||
| #define DSIM_CONFIG				(0x30) | ||||
| #define DSIM_CONFIG_NONCONTINUOUS_CLOCK_LANE	(1 << 31) | ||||
| #define DSIM_CONFIG_CLKLANE_STOP_START		(1 << 30) | ||||
| #define DSIM_CONFIG_FLUSH_VS			(1 << 29) | ||||
| #define DSIM_CONFIG_SYNC_INFORM			(1 << 27) | ||||
| #define DSIM_CONFIG_BURST_MODE			(1 << 26) | ||||
| #define DSIM_CONFIG_HSYNC_PRESERVE		(1 << 25) | ||||
| #define DSIM_CONFIG_HSE_DISABLE			(1 << 23) | ||||
| #define DSIM_CONFIG_HFP_DISABLE			(1 << 22) | ||||
| #define DSIM_CONFIG_HBP_DISABLE			(1 << 21) | ||||
| #define DSIM_CONFIG_HSA_DISABLE			(1 << 20) | ||||
| #define DSIM_CONFIG_CPRS_EN			(1 << 19) | ||||
| #define DSIM_CONFIG_VIDEO_MODE			(1 << 18) | ||||
| #define DSIM_CONFIG_VC_CONTROL			(1 << 17) | ||||
| #define DSIM_CONFIG_VC_ID(_x)			((_x) << 16) | ||||
| #define DSIM_CONFIG_VC_ID_MASK			(0x3 << 16) | ||||
| #define DSIM_CONFIG_PIXEL_FORMAT(_x)		((_x) << 12) | ||||
| #define DSIM_CONFIG_PIXEL_FORMAT_MASK		(0x7 << 12) | ||||
| #define DSIM_CONFIG_MULTI_PIX			(1 << 11) | ||||
| #define DSIM_CONFIG_Q_CHANNEL_EN		(1 << 10) | ||||
| #define DSIM_CONFIG_PER_FRAME_READ_EN		(1 << 9) | ||||
| #define DSIM_CONFIG_NUM_OF_DATA_LANE(_x)	((_x) << 5) | ||||
| #define DSIM_CONFIG_NUM_OF_DATA_LANE_MASK	(0x3 << 5) | ||||
| #define DSIM_CONFIG_LANES_EN(_x)		(((_x) & 0x1f) << 0) | ||||
| 
 | ||||
| /* Interrupt source register */ | ||||
| #define DSIM_INTSRC				(0x34) | ||||
| #define DSIM_INTSRC_PLL_STABLE			(1 << 31) | ||||
| #define DSIM_INTSRC_SW_RST_RELEASE		(1 << 30) | ||||
| #define DSIM_INTSRC_SFR_PL_FIFO_EMPTY		(1 << 29) | ||||
| #define DSIM_INTSRC_SFR_PH_FIFO_EMPTY		(1 << 28) | ||||
| #define DSIM_INTSRC_SFR_PH_FIFO_OVERFLOW	(1 << 26) | ||||
| #define DSIM_INTSRC_BUS_TURN_OVER		(1 << 25) | ||||
| #define DSIM_INTSRC_FRAME_DONE			(1 << 24) | ||||
| #define DSIM_INTSRC_ABNRMAL_CMD_ST		(1 << 22) | ||||
| #define DSIM_INTSRC_LPDR_TOUT			(1 << 21) | ||||
| #define DSIM_INTSRC_BTA_TOUT			(1 << 20) | ||||
| #define DSIM_INTSRC_HSYNC_TOUT			(1 << 19) | ||||
| #define DSIM_INTSRC_RX_DATA_DONE		(1 << 18) | ||||
| #define DSIM_INTSRC_ERR_RX_ECC			(1 << 15) | ||||
| 
 | ||||
| /* Interrupt mask register */ | ||||
| #define DSIM_INTMSK				(0x38) | ||||
| #define DSIM_INTMSK_PLL_STABLE			(1 << 31) | ||||
| #define DSIM_INTSRC_SW_RST_RELEASE		(1 << 30) | ||||
| #define DSIM_INTMSK_SFR_PL_FIFO_EMPTY		(1 << 29) | ||||
| #define DSIM_INTMSK_SFR_PH_FIFO_EMPTY		(1 << 28) | ||||
| #define DSIM_INTMSK_SFR_PH_FIFO_OVERFLOW	(1 << 26) | ||||
| #define DSIM_INTMSK_BUS_TURN_OVER		(1 << 25) | ||||
| #define DSIM_INTMSK_FRAME_DONE			(1 << 24) | ||||
| #define DSIM_INTMSK_ABNORMAL_CMD_ST		(1 << 22) | ||||
| #define DSIM_INTMSK_LPDR_TOUT			(1 << 21) | ||||
| #define DSIM_INTMSK_BTA_TOUT			(1 << 20) | ||||
| #define DSIM_INTMSK_HSYNC_TOUT			(1 << 19) | ||||
| #define DSIM_INTMSK_RX_DATA_DONE		(1 << 18) | ||||
| #define DSIM_INTMSK_ERR_RX_ECC			(1 << 15) | ||||
| 
 | ||||
| /* Packet Header FIFO register */ | ||||
| #define DSIM_PKTHDR				(0x3c) | ||||
| #define DSIM_PKTHDR_ID(_x)			((_x) << 0) | ||||
| #define DSIM_PKTHDR_DATA0(_x)			((_x) << 8) | ||||
| #define DSIM_PKTHDR_DATA1(_x)			((_x) << 16) | ||||
| 
 | ||||
| /* Payload FIFO register */ | ||||
| #define DSIM_PAYLOAD				(0x40) | ||||
| 
 | ||||
| /* Read FIFO register */ | ||||
| #define DSIM_RXFIFO				(0x44) | ||||
| 
 | ||||
| /* SFR control Register for Stanby & Shadow*/ | ||||
| #define DSIM_SFR_CTRL				(0x48) | ||||
| #define DSIM_SFR_CTRL_STANDBY			(1 << 4) | ||||
| #define DSIM_SFR_CTRL_SHADOW_UPDATE		(1 << 1) | ||||
| #define DSIM_SFR_CTRL_SHADOW_EN			(1 << 0) | ||||
| 
 | ||||
| /* FIFO status and control register */ | ||||
| #define DSIM_FIFOCTRL				(0x4C) | ||||
| #define DSIM_FIFOCTRL_NUMBER_OF_PH_SFR(_x)	(((_x) & 0x3f) << 16) | ||||
| #define DSIM_FIFOCTRL_EMPTY_RX			(1 << 12) | ||||
| #define DSIM_FIFOCTRL_FULL_PH_SFR		(1 << 11) | ||||
| #define DSIM_FIFOCTRL_FULL_PL_SFR		(1 << 9) | ||||
| #define DSIM_FIFOCTRL_INIT_RX			(1 << 2) | ||||
| #define DSIM_FIFOCTRL_INIT_SFR			(1 << 1) | ||||
| 
 | ||||
| /* Muli slice setting register*/ | ||||
| #define DSIM_CPRS_CTRL				(0x58) | ||||
| #define DSIM_CPRS_CTRL_MULI_SLICE_PACKET	(1 << 3) | ||||
| #define DSIM_CPRS_CTRL_NUM_OF_SLICE(_x)		((_x) << 0) | ||||
| #define DSIM_CPRS_CTRL_NUM_OF_SLICE_MASK	(0x7 << 0) | ||||
| 
 | ||||
| /*Slice01 size register*/ | ||||
| #define DSIM_SLICE01				(0x5C) | ||||
| #define DSIM_SLICE01_SIZE_OF_SLICE1(_x)		((_x) << 16) | ||||
| #define DSIM_SLICE01_SIZE_OF_SLICE1_MASK	(0x1fff << 16) | ||||
| #define DSIM_SLICE01_SIZE_OF_SLICE0(_x)		((_x) << 0) | ||||
| #define DSIM_SLICE01_SIZE_OF_SLICE0_MASK	(0x1fff << 0) | ||||
| 
 | ||||
| /*Slice23 size register*/ | ||||
| #define DSIM_SLICE23				(0x60) | ||||
| #define DSIM_SLICE23_SIZE_OF_SLICE3(_x)		((_x) << 16) | ||||
| #define DSIM_SLICE23_SIZE_OF_SLICE3_MASK	(0x1fff << 16) | ||||
| #define DSIM_SLICE23_SIZE_OF_SLICE2(_x)		((_x) << 0) | ||||
| #define DSIM_SLICE23_SIZE_OF_SLICE2_MASK	(0x1fff << 0) | ||||
| 
 | ||||
| /* Command configuration register */ | ||||
| #define DSIM_CMD_CONFIG				(0x78) | ||||
| #define DSIM_CMD_CONFIG_TE_DETECT_POLARITY	(1 << 25) | ||||
| #define DSIM_CMD_CONFIG_VSYNC_DETECT_POLARITY	(1 << 24) | ||||
| #define DSIM_CMD_CONFIG_PKT_GO_RDY		(1 << 22) | ||||
| #define DSIM_CMD_CONFIG_PKT_GO_EN		(1 << 21) | ||||
| #define DSIM_CMD_CONFIG_CMD_CTRL_SEL		(1 << 20) | ||||
| #define DSIM_CMD_CONFIG_PKT_SEND_CNT(_x)	((_x) << 8) | ||||
| #define DSIM_CMD_CONFIG_PKT_SEND_CNT_MASK	(0xfff << 8) | ||||
| #define DSIM_CMD_CONFIG_MULTI_CMD_PKT_EN	(1 << 7) | ||||
| #define DSIM_CMD_CONFIG_MULTI_PKT_CNT(_x)	((_x) << 0) | ||||
| #define DSIM_CMD_CONFIG_MULTI_PKT_CNT_MASK	(0xffff << 0) | ||||
| 
 | ||||
| /* TE based command register*/ | ||||
| #define DSIM_CMD_TE_CTRL0			(0x7C) | ||||
| #define DSIM_CMD_TE_CTRL0_TIME_STABLE_VFP(_x)	((_x) << 16) | ||||
| #define DSIM_CMD_TE_CTRL0_TIME_STABLE_VFP_MASK	(0xffff << 16) | ||||
| #define DSIM_CMD_TE_CTRL0_TIME_VSYNC_TOUT(_x)	((_x) << 0) | ||||
| #define DSIM_CMD_TE_CTRL0_TIME_VSYNC_TOUT_MASK	(0xffff << 0) | ||||
| 
 | ||||
| /* TE based command register*/ | ||||
| #define DSIM_CMD_TE_CTRL1			(0x80) | ||||
| #define DSIM_CMD_TE_CTRL1_TIME_TE_PROTECT_ON(_x) ((_x) << 16) | ||||
| #define DSIM_CMD_TE_CTRL1_TIME_TE_PROTECT_ON_MASK (0xffff << 16) | ||||
| #define DSIM_CMD_TE_CTRL1_TIME_TE_TOUT(_x)	((_x) << 0) | ||||
| #define DSIM_CMD_TE_CTRL1_TIME_TE_TOUT_MASK	(0xffff << 0) | ||||
| 
 | ||||
| /*Command Mode Status register*/ | ||||
| #define DSIM_CMD_STATUS				(0x87) | ||||
| #define	DSIM_CMD_STATUS_ABNORMAL_CAUSE_ST(_x)	(((_x) & 0x3ff) << 0) | ||||
| 
 | ||||
| /*BIST generation register*/ | ||||
| #define	DSIM_BIST_GEN				(0x88) | ||||
| #define DSIM_BIST_GEN_BIST_VFP(_x)		((_x) << 20) | ||||
| #define DSIM_BIST_GEN_BIST_VFP_MASK		(0x7ff << 20) | ||||
| #define DSIM_BIST_GEN_BIST_START		(1 << 16) | ||||
| #define	DSIM_BIST_GEN_COLORIMETRIC_FORMAT	(1 << 6) | ||||
| #define	DSIM_BIST_GEN_HSYNC_POLARITY		(1 << 5) | ||||
| #define	DSIM_BIST_GEN_VSYNC_POLARITY		(1 << 4) | ||||
| #define	DSIM_BIST_GEN_BIST_BAR_WIDTH		(1 << 3) | ||||
| #define	DSIM_BIST_GEN_BIST_TYPE(_x)		((_x) << 1) | ||||
| #define	DSIM_BIST_GEN_BIST_TYPE_MASK		(0x3 << 1) | ||||
| #define	DSIM_BIST_GEN_BIST_EN			(1 << 0) | ||||
| 
 | ||||
| /*DSIM to CSI loopback register*/ | ||||
| #define	DSIM_CSIS_LB				(0x8C) | ||||
| #define	DSIM_CSIS_LB_CSIS_LB_EN			(1 << 8) | ||||
| #define DSIM_CSIS_LB_CSIS_PH(_x)		((_x) << 0) | ||||
| #define DSIM_CSIS_LB_CSIS_PH_MASK		(0xff << 0) | ||||
| 
 | ||||
| /* PLL control register */ | ||||
| #define DSIM_PLLCTRL				(0x94) | ||||
| #define DSIM_PLLCTRL_DPDN_SWAP_CLK		(1 << 25) | ||||
| #define DSIM_PLLCTRL_DPDN_SWAP_DATA		(1 << 24) | ||||
| #define DSIM_PLLCTRL_PLL_EN			(1 << 23) | ||||
| #define DSIM_PLLCTRL_PMS_MASK			(0x7ffff << 0) | ||||
| 
 | ||||
| /* M_PLL CTR1 register*/ | ||||
| #define DSIM_PLL_CTRL1				(0x98) | ||||
| #define DSIM_PLL_CTRL1_M_PLL_CTRL1		(0xffffffff << 0) | ||||
| 
 | ||||
| /* M_PLL CTR1 register*/ | ||||
| #define DSIM_PLL_CTRL2				(0x9C) | ||||
| #define DSIM_PLL_CTRL2_M_PLL_CTRL2		(0xffffffff << 0) | ||||
| 
 | ||||
| /* PLL timer register */ | ||||
| #define DSIM_PLLTMR				(0xa0) | ||||
| 
 | ||||
| /* D-PHY Master & Slave Analog block characteristics control register */ | ||||
| #define DSIM_PHYCTRL				(0xa4) | ||||
| #define DSIM_PHYCTRL_VREG			(1 << 26) | ||||
| #define DSIM_PHYCTRL_B_DPHYCTL0(_x)		((_x) << 0) | ||||
| #define DSIM_PHYCTRL_B_DPHYCTL0_MASK		(0x3ff << 0) | ||||
| 
 | ||||
| /* D-PHY Master global operating timing register */ | ||||
| #define DSIM_PHYTIMING				(0xb4) | ||||
| #define DSIM_PHYTIMING_M_TLPXCTL(_x)		((_x) << 8) | ||||
| #define DSIM_PHYTIMING_M_TLPXCTL_MASK		(0xff << 8) | ||||
| #define DSIM_PHYTIMING_M_THSEXITCTL(_x)		((_x) << 0) | ||||
| #define DSIM_PHYTIMING_M_THSEXITCTL_MASK	(0xff << 0) | ||||
| 
 | ||||
| #define DSIM_PHYTIMING1				(0xb8) | ||||
| #define DSIM_PHYTIMING1_M_TCLKPRPRCTL(_x)	((_x) << 24) | ||||
| #define DSIM_PHYTIMING1_M_TCLKPRPRCTL_MASK	(0xff << 24) | ||||
| #define DSIM_PHYTIMING1_M_TCLKZEROCTL(_x)	((_x) << 16) | ||||
| #define DSIM_PHYTIMING1_M_TCLKZEROCTL_MASK	(0xff << 16) | ||||
| #define DSIM_PHYTIMING1_M_TCLKPOSTCTL(_x)	((_x) << 8) | ||||
| #define DSIM_PHYTIMING1_M_TCLKPOSTCTL_MASK	(0xff << 8) | ||||
| #define DSIM_PHYTIMING1_M_TCLKTRAILCTL(_x)	((_x) << 0) | ||||
| #define DSIM_PHYTIMING1_M_TCLKTRAILCTL_MASK	(0xff << 0) | ||||
| 
 | ||||
| #define DSIM_PHYTIMING2				(0xbc) | ||||
| #define DSIM_PHYTIMING2_M_THSPRPRCTL(_x)	((_x) << 16) | ||||
| #define DSIM_PHYTIMING2_M_THSPRPRCTL_MASK	(0xff << 16) | ||||
| #define DSIM_PHYTIMING2_M_THSZEROCTL(_x)	((_x) << 8) | ||||
| #define DSIM_PHYTIMING2_M_THSZEROCTL_MASK	(0xff << 8) | ||||
| #define DSIM_PHYTIMING2_M_THSTRAILCTL(_x)	((_x) << 0) | ||||
| #define DSIM_PHYTIMING2_M_THSTRAILCTL_MASK	(0xff << 0) | ||||
| 
 | ||||
| #endif /* _REGS_DSIM_H */ | ||||
							
								
								
									
										6
									
								
								drivers/video/fbdev/exynos/decon_8890/vpp/Kconfig
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										6
									
								
								drivers/video/fbdev/exynos/decon_8890/vpp/Kconfig
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,6 @@ | |||
| config EXYNOS_VPP | ||||
| 	bool "Samsung Exynos Video Post Processor driver" | ||||
| 	depends on EXYNOS_DECON_8890 | ||||
| 	default y | ||||
| 	help | ||||
| 	  Enable VPP driver. | ||||
							
								
								
									
										2
									
								
								drivers/video/fbdev/exynos/decon_8890/vpp/Makefile
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										2
									
								
								drivers/video/fbdev/exynos/decon_8890/vpp/Makefile
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,2 @@ | |||
| vpp-objs := vpp_drv.o vpp_reg_8890.o | ||||
| obj-$(CONFIG_EXYNOS_VPP) += vpp.o | ||||
							
								
								
									
										233
									
								
								drivers/video/fbdev/exynos/decon_8890/vpp/regs-vpp.h
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										233
									
								
								drivers/video/fbdev/exynos/decon_8890/vpp/regs-vpp.h
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,233 @@ | |||
| /* linux/drivers/video/decon_2.0/regs-vpp.h
 | ||||
|  * | ||||
|  * Copyright (c) 2014 Samsung Electronics Co., Ltd. | ||||
|  *		http://www.samsung.com
 | ||||
|  * | ||||
|  * Register definition file for Samsung vpp driver | ||||
|  * | ||||
|  * 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. | ||||
|  */ | ||||
| 
 | ||||
| #ifndef VPP_REGS_H_ | ||||
| #define VPP_REGS_H_ | ||||
| 
 | ||||
| /* IDMA_VG(R)x_ENABLE */ | ||||
| #define VG_ENABLE				(0x00) | ||||
| 
 | ||||
| #define VG_ENABLE_OP_STATUS			(1 << 2) | ||||
| #define VG_ENABLE_SFR_UPDATE_FORCE		(1 << 4) | ||||
| #define VG_ENABLE_INT_CLOCK_GATE_EN		(1 << 8) | ||||
| #define VG_ENABLE_SRAM_CLOCK_GATE_EN		(1 << 9) | ||||
| #define VG_ENABLE_SFR_CLOCK_GATE_EN		(1 << 10) | ||||
| #define VG_ENABLE_SCALER_CLOCK_GATE_EN		(1 << 11) | ||||
| #define VG_ENABLE_RT_PATH_EN			(1 << 16) | ||||
| #define VG_ENABLE_RT_PATH_EN_S			(1 << 17) | ||||
| #define VG_ENABLE_SRESET			(1 << 24) | ||||
| #define VG_ENABLE_VSD_SRESET_MASK		(1 << 25) | ||||
| 
 | ||||
| /* IDMA_VG(R)x_IRQ */ | ||||
| #define VG_IRQ					(0x04) | ||||
| 
 | ||||
| #define VG_IRQ_ENABLE				(1 << 0) | ||||
| #define VG_IRQ_FRAMEDONE_MASK			(1 << 1) | ||||
| #define VG_IRQ_DEADLOCK_STATUS_MASK		(1 << 2) | ||||
| #define VG_IRQ_READ_SLAVE_ERROR_MASK		(1 << 4) | ||||
| #define VG_IRQ_HW_RESET_DONE_MASK		(1 << 5) | ||||
| #define VG_IRQ_SFR_UPDATE_DONE_MASK		(1 << 6) | ||||
| #define VG_IRQ_FRAMEDONE			(1 << 16) | ||||
| #define VG_IRQ_DEADLOCK_STATUS			(1 << 17) | ||||
| #define VG_IRQ_READ_SLAVE_ERROR			(1 << 19) | ||||
| #define VG_IRQ_HW_RESET_DONE			(1 << 20) | ||||
| #define VG_IRQ_SFR_UPDATE_DONE			(1 << 21) | ||||
| 
 | ||||
| /* IDMA_VG(R)x_IN_CON */ | ||||
| #define VG_IN_CON				(0x08) | ||||
| 
 | ||||
| #define VG_IN_CON_BLOCKING_FEATURE_EN		(1 << 3) | ||||
| #define VG_IN_CON_CHROMINANCE_STRIDE_EN		(1 << 4) | ||||
| #define VG_IN_CON_SCAN_MODE_MASK		(3 << 5) | ||||
| #define VG_IN_CON_SCAN_MODE_PRO_TO_PRO		(1 << 5) | ||||
| #define VG_IN_CON_SCAN_MODE_INT_TO_PRO		(2 << 5) | ||||
| #define VG_IN_CON_SCAN_MODE_INT_TO_INT		(3 << 5) | ||||
| #define VG_IN_CON_IN_ROTATION_MASK		(7 << 8) | ||||
| #define VG_IN_CON_IN_ROTATION_X_FLIP		(1 << 8) | ||||
| #define VG_IN_CON_IN_ROTATION_Y_FLIP		(2 << 8) | ||||
| #define VG_IN_CON_IN_ROTATION_180		(3 << 8) | ||||
| #define VG_IN_CON_IN_ROTATION_90		(4 << 8) | ||||
| #define VG_IN_CON_IN_ROTATION_90_X_FLIP		(5 << 8) | ||||
| #define VG_IN_CON_IN_ROTATION_90_Y_FLIP		(6 << 8) | ||||
| #define VG_IN_CON_IN_ROTATION_270		(7 << 8) | ||||
| #define VG_IN_CON_IMG_FORMAT_MASK		(31 << 11) | ||||
| #define VG_IN_CON_IMG_FORMAT_ARGB8888		(0 << 11) | ||||
| #define VG_IN_CON_IMG_FORMAT_ABGR8888		(1 << 11) | ||||
| #define VG_IN_CON_IMG_FORMAT_RGBA8888		(2 << 11) | ||||
| #define VG_IN_CON_IMG_FORMAT_BGRA8888		(3 << 11) | ||||
| #define VG_IN_CON_IMG_FORMAT_XRGB8888		(4 << 11) | ||||
| #define VG_IN_CON_IMG_FORMAT_XBGR8888		(5 << 11) | ||||
| #define VG_IN_CON_IMG_FORMAT_RGBX8888		(6 << 11) | ||||
| #define VG_IN_CON_IMG_FORMAT_BGRX8888		(7 << 11) | ||||
| #define VG_IN_CON_IMG_FORMAT_RGB565		(8 << 11) | ||||
| #define VG_IN_CON_IMG_FORMAT_YUV422_2P		(20 << 11) | ||||
| #define VG_IN_CON_IMG_FORMAT_YVU422_2P		(21 << 11) | ||||
| #define VG_IN_CON_IMG_FORMAT_YUV422_3P		(22 << 11) | ||||
| #define VG_IN_CON_IMG_FORMAT_YUV420_2P		(24 << 11) | ||||
| #define VG_IN_CON_IMG_FORMAT_YVU420_2P		(25 << 11) | ||||
| #define VG_IN_CON_IMG_FORMAT_YUV420_3P		(26 << 11) | ||||
| #define VG_IN_CON_BURST_LENGTH_MASK		(0xF << 24) | ||||
| #define VG_IN_CON_BURST_LENGTH_0		(0 << 24) | ||||
| #define VG_IN_CON_BURST_LENGTH_1		(1 << 24) | ||||
| #define VG_IN_CON_BURST_LENGTH_2		(2 << 24) | ||||
| #define VG_IN_CON_BURST_LENGTH_3		(3 << 24) | ||||
| #define VG_IN_CON_IN_AFBC_EN			(1 << 7) | ||||
| 
 | ||||
| /* IDMA_VG(R)x_OUT_CON */ | ||||
| #define VG_OUT_CON				(0x0C) | ||||
| 
 | ||||
| #define VG_OUT_CON_RGB_TYPE_MASK		(3 << 17) | ||||
| #define VG_OUT_CON_RGB_TYPE_601_NARROW		(0 << 17) | ||||
| #define VG_OUT_CON_RGB_TYPE_601_WIDE		(1 << 17) | ||||
| #define VG_OUT_CON_RGB_TYPE_709_NARROW		(2 << 17) | ||||
| #define VG_OUT_CON_RGB_TYPE_709_WIDE		(3 << 17) | ||||
| #define VG_OUT_CON_FRAME_ALPHA_MASK		(0xFF << 24) | ||||
| #define VG_OUT_CON_FRAME_ALPHA(x)		(x << 24) | ||||
| 
 | ||||
| /* IDMA_VG(R)x_SRC_SIZE */ | ||||
| #define VG_SRC_SIZE				(0x10) | ||||
| 
 | ||||
| #define VG_SRC_SIZE_HEIGHT_MASK			(0x1FFF << 16) | ||||
| #define VG_SRC_SIZE_HEIGHT(x)			((x) << 16) | ||||
| #define VG_SRC_SIZE_WIDTH_MASK			(0x1FFF << 0) | ||||
| #define VG_SRC_SIZE_WIDTH(x)			((x) << 0) | ||||
| 
 | ||||
| /* IDMA_VG(R)x_SRC_OFFSET */ | ||||
| #define VG_SRC_OFFSET				(0x14) | ||||
| 
 | ||||
| #define VG_SRC_OFFSET_Y_MASK			(0x1FFF << 16) | ||||
| #define VG_SRC_OFFSET_Y(x)			((x) << 16) | ||||
| #define VG_SRC_OFFSET_X_MASK			(0x1FFF << 0) | ||||
| #define VG_SRC_OFFSET_X(x)			((x) << 0) | ||||
| 
 | ||||
| /* IDMA_VG(R)x_IMG_SIZE */ | ||||
| #define VG_IMG_SIZE				(0x18) | ||||
| 
 | ||||
| #define VG_IMG_SIZE_HEIGHT_MASK			(0x1FFF << 16) | ||||
| #define VG_IMG_SIZE_HEIGHT(x)			((x) << 16) | ||||
| #define VG_IMG_SIZE_WIDTH_MASK			(0x1FFF << 0) | ||||
| #define VG_IMG_SIZE_WIDTH(x)			((x) << 0) | ||||
| 
 | ||||
| /* IDMA_x_PINGPONG_UPDATE */ | ||||
| #define VG_PINGPONG_UPDATE			(0x1C) | ||||
| #define VG_ADDR_PINGPONG_UPDATE			(1 << 0) | ||||
| 
 | ||||
| /* IDMA_VG(R)x_CHROMINANCE_STRIDE */ | ||||
| #define VG_CHROMINANCE_STRIDE			(0x20) | ||||
| 
 | ||||
| #define VG_CHROMINANCE_STRIDE_MASK		(0x1FFF << 0) | ||||
| #define VG_CHROMINANCE_STRIDE_SIZE(x)		((x) << 0) | ||||
| 
 | ||||
| /* IDMA_VG(R)x_BLK_OFFSET */ | ||||
| #define VG_BLK_OFFSET				(0x24) | ||||
| 
 | ||||
| #define VG_BLK_OFFSET_Y_MASK			(0x1FFF << 16) | ||||
| #define VG_BLK_OFFSET_Y(x)			((x) << 16) | ||||
| #define VG_BLK_OFFSET_X_MASK			(0x1FFF << 0) | ||||
| #define VG_BLK_OFFSET_X(x)			((x) << 0) | ||||
| 
 | ||||
| /* IDMA_VG(R)x_BLK_SIZE	*/ | ||||
| #define VG_BLK_SIZE				(0x28) | ||||
| 
 | ||||
| #define VG_BLK_SIZE_HEIGHT_MASK			(0x1FFF << 16) | ||||
| #define VG_BLK_SIZE_HEIGHT(x)			((x) << 16) | ||||
| #define VG_BLK_SIZE_WIDTH_MASK			(0x1FFF << 0) | ||||
| #define VG_BLK_SIZE_WIDTH(x)			((x) << 0) | ||||
| 
 | ||||
| /* IDMA_VG(R)x_SCALED_SIZE */ | ||||
| #define VG_SCALED_SIZE				(0x2C) | ||||
| 
 | ||||
| #define VG_SCALED_SIZE_HEIGHT_MASK		(0x1FFF << 16) | ||||
| #define VG_SCALED_SIZE_HEIGHT(x)		((x) << 16) | ||||
| #define VG_SCALED_SIZE_WIDTH_MASK		(0x1FFF << 0) | ||||
| #define VG_SCALED_SIZE_WIDTH(x)			((x) << 0) | ||||
| 
 | ||||
| /* IDMA_VG(R)x_H_RATIO */ | ||||
| #define VG_H_RATIO				(0x44) | ||||
| 
 | ||||
| #define VG_H_RATIO_MASK				(0xFFFFFF << 0) | ||||
| #define VG_H_RATIO_VALUE(x)			((x) << 0) | ||||
| 
 | ||||
| /* IDMA_VG(R)x_V_RATIO */ | ||||
| #define VG_V_RATIO				(0x48) | ||||
| 
 | ||||
| #define VG_V_RATIO_MASK				(0xFFFFFF << 0) | ||||
| #define VG_V_RATIO_VALUE(x)			((x) << 0) | ||||
| 
 | ||||
| /* IDMA_VG(R)x LOOKUP TABLE */ | ||||
| #define VG_QOS_LUT07_00				(0x60) | ||||
| #define VG_QOS_LUT15_08				(0x64) | ||||
| 
 | ||||
| /* IDMA_VG(R)x BASE ADDRESS CONTROL */ | ||||
| #define VG_BASE_ADDR_CON			(0x70) | ||||
| 
 | ||||
| #define VG_BASE_ADDR_CON_MASK(n)		(1 << (x)) | ||||
| #define VG_BASE_ADDR_CON_PINGPONG_MASK		(3 << 16) | ||||
| #define VG_BASE_ADDR_CON_PINGPONG(n)		((x) << 16) | ||||
| #define VG_BASE_ADDR_CON_CURRENT(n)		((x) >> 24) | ||||
| #define VG_BASE_ADDR_CON_CURRENT_INDEX_INIT	(1 << 31) | ||||
| 
 | ||||
| /* IDMA_VG(R)x BASE ADDRESS */ | ||||
| #define VG_BASE_ADDR_Y(n)			(0x74 + (n) * 0x4) | ||||
| #define VG_BASE_ADDR_Y_EVEN(n)			(0x84 + (n) * 0x4) | ||||
| #define VG_BASE_ADDR_CB(n)			(0x94 + (n) * 0x4) | ||||
| #define VG_BASE_ADDR_CB_EVEN(n)			(0xA4 + (n) * 0x4) | ||||
| 
 | ||||
| /* IDMA_VG(R)x scaling filter */ | ||||
| #define VG_H_COEF(n, s, x)	(0x290 + (n) * 0x4 + (s) * 0x24 + (x) * 0x200) | ||||
| #define VG_V_COEF(n, s, x)	(0x200 + (n) * 0x4 + (s) * 0x24 + (x) * 0x200) | ||||
| 
 | ||||
| /* IDMA_VG(R)x Y(R) start H position */ | ||||
| #define VG_YHPOSITION0				(0x5B0) | ||||
| 
 | ||||
| /* IDMA_VG(R)x Y(R) start V position */ | ||||
| #define VG_YVPOSITION0				(0x5B4) | ||||
| 
 | ||||
| /* IDMA_VG(R)x CB(G)/CR(B) H position */ | ||||
| #define VG_CHPOSITION0				(0x5B8) | ||||
| 
 | ||||
| /* IDMA_VG(R)x CB(G)/CR(B) V position */ | ||||
| #define VG_CVPOSITION0				(0x5BC) | ||||
| 
 | ||||
| /* IDMA_VG(R)x Y(R) start H position for odd frame */ | ||||
| #define VG_YHPOSITION1				(0x5C0) | ||||
| 
 | ||||
| /* IDMA_VG(R)x Y(R) start V position for odd frame */ | ||||
| #define VG_YVPOSITION1				(0x5C4) | ||||
| 
 | ||||
| /* IDMA_VG(R)x CB(G)/CR(B) H position for odd frame */ | ||||
| #define VG_CHPOSITION1				(0x5C8) | ||||
| 
 | ||||
| /* IDMA_VG(R)x CB(G)/CR(B) V position for odd frame */ | ||||
| #define VG_CVPOSITION1				(0x5CC) | ||||
| 
 | ||||
| #define VG_POSITION_F_MASK			(0xFFFFF << 0) | ||||
| 
 | ||||
| /* IDMA_VG(R)x Deadlock Counter Number */ | ||||
| #define VG_DEADLOCK_NUM				(0xA00) | ||||
| 
 | ||||
| /* IDMA_VG(R)x Sharpness Enhancer Control */ | ||||
| #define VG_SHE_CON				(0xA0C) | ||||
| 
 | ||||
| #define VG_SHE_CON_SHARP_PATTERN_MASK		(1 << 3) | ||||
| #define VG_SHE_CON_SHARP_PATTERN_ENABLE		(0 << 3) | ||||
| #define VG_SHE_CON_SHARP_EFFECT_MASK		(7 << 0) | ||||
| #define VG_SHE_CON_SHARP_EFFECT_MAX		(7 << 0) | ||||
| #define VG_SHE_CON_SHARP_EN			(1 << 4) | ||||
| #define VG_SHE_CON_SHARP_BYPASS			(1 << 5) | ||||
| 
 | ||||
| /* IDMA_VG(R)x SMART Interface Pixel Number */ | ||||
| #define VG_SMART_IF_PIXEL_NUM			(0xA48) | ||||
| 
 | ||||
| /* IDMA_VG(R)x Dynamic clock gating */ | ||||
| #define VG_DYNAMIC_GATING_ENABLE		(0xA54) | ||||
| #endif | ||||
							
								
								
									
										252
									
								
								drivers/video/fbdev/exynos/decon_8890/vpp/vpp.h
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										252
									
								
								drivers/video/fbdev/exynos/decon_8890/vpp/vpp.h
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,252 @@ | |||
| /* linux/drivers/video/exynos/decon/vpp_core.h
 | ||||
|  * | ||||
|  * Copyright (c) 2015 Samsung Electronics Co., Ltd. | ||||
|  *		http://www.samsung.com
 | ||||
|  * | ||||
|  * header file for Samsung EXYNOS5 SoC series VPP driver | ||||
| 
 | ||||
|  * 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. | ||||
|  */ | ||||
| 
 | ||||
| #ifndef VPP_H_ | ||||
| #define VPP_H_ | ||||
| 
 | ||||
| #include <linux/delay.h> | ||||
| #include <linux/sched.h> | ||||
| #include <linux/spinlock.h> | ||||
| #include <linux/types.h> | ||||
| #include <linux/videodev2.h> | ||||
| #include <linux/io.h> | ||||
| #include <linux/pm_runtime.h> | ||||
| #include <linux/pm_qos.h> | ||||
| #include <linux/of.h> | ||||
| #include <linux/of_address.h> | ||||
| #include <linux/exynos_iovmm.h> | ||||
| #include <media/exynos_mc.h> | ||||
| 
 | ||||
| #include "regs-vpp.h" | ||||
| #include "vpp_common.h" | ||||
| #include "../decon.h" | ||||
| 
 | ||||
| #define VPP_PADS_NUM	1 | ||||
| #define DEV		(&vpp->pdev->dev) | ||||
| 
 | ||||
| #define is_rotation(config) (config->vpp_parm.rot >= VPP_ROT_90) | ||||
| #define is_normal(config) (VPP_ROT_NORMAL) | ||||
| #define is_yuv(config) ((config->format >= DECON_PIXEL_FORMAT_NV16) && (config->format < DECON_PIXEL_FORMAT_MAX)) | ||||
| #define is_yuv422(config) ((config->format >= DECON_PIXEL_FORMAT_NV16) && (config->format <= DECON_PIXEL_FORMAT_YVU422_3P)) | ||||
| #define is_yuv420(config) ((config->format >= DECON_PIXEL_FORMAT_NV12) && (config->format <= DECON_PIXEL_FORMAT_YVU420M)) | ||||
| #define is_rgb(config) ((config->format >= DECON_PIXEL_FORMAT_ARGB_8888) && (config->format <= DECON_PIXEL_FORMAT_RGB_565)) | ||||
| #define is_rgb16(config) ((config->format == DECON_PIXEL_FORMAT_RGB_565)) | ||||
| #define is_ayv12(config) (config->format == DECON_PIXEL_FORMAT_YVU420) | ||||
| #define is_fraction(x) ((x) >> 15) | ||||
| #define is_vpp0_series(vpp) ((vpp->id == 0 || vpp->id == 1 || vpp->id == 2 || vpp->id == 3)) | ||||
| #define is_vgr(vpp) ((vpp->id == 6) || (vpp->id == 7)) | ||||
| #define is_vgr1(vpp) (vpp->id == 7) | ||||
| #define is_g(vpp) ((vpp->id == 0) || (vpp->id == 1) || (vpp->id == 4) || (vpp->id == 5)) | ||||
| #define is_wb(vpp) (vpp->id == 8) | ||||
| #define is_scaling(vpp) ((vpp->h_ratio != (1 << 20)) || (vpp->v_ratio != (1 << 20))) | ||||
| #define is_scale_down(vpp) ((vpp->h_ratio > (1 << 20)) || (vpp->v_ratio > (1 << 20))) | ||||
| 
 | ||||
| #define vpp_err(fmt, ...)					\ | ||||
| 	do {							\ | ||||
| 		pr_err(pr_fmt(fmt), ##__VA_ARGS__);		\ | ||||
| 		exynos_ss_printk(fmt, ##__VA_ARGS__);		\ | ||||
| 	} while (0) | ||||
| 
 | ||||
| #define vpp_info(fmt, ...)					\ | ||||
| 	do {							\ | ||||
| 		pr_info(pr_fmt(fmt), ##__VA_ARGS__);		\ | ||||
| 	} while (0) | ||||
| 
 | ||||
| #define vpp_dbg(fmt, ...)					\ | ||||
| 	do {							\ | ||||
| 		pr_debug(pr_fmt(fmt), ##__VA_ARGS__);		\ | ||||
| 	} while (0) | ||||
| 
 | ||||
| enum vpp_dev_state { | ||||
| 	VPP_RUNNING, | ||||
| 	VPP_POWER_ON, | ||||
| 	VPP_STOPPING, | ||||
| }; | ||||
| 
 | ||||
| struct vpp_resources { | ||||
| 	struct clk *gate; | ||||
| }; | ||||
| 
 | ||||
| struct vpp_fraction { | ||||
| 	u32 y_x; | ||||
| 	u32 y_y; | ||||
| 	u32 c_x; | ||||
| 	u32 c_y; | ||||
| 	u32 w; | ||||
| 	u32 h; | ||||
| }; | ||||
| 
 | ||||
| struct vpp_minlock_entry { | ||||
| 	bool rotation; | ||||
| 	u32 scalefactor; | ||||
| 	u32 dvfsfreq; | ||||
| }; | ||||
| 
 | ||||
| struct vpp_minlock_table { | ||||
| 	struct list_head node; | ||||
| 	u16 width; | ||||
| 	u16 height; | ||||
| 	int num_entries; | ||||
| 	struct vpp_minlock_entry entries[0]; | ||||
| }; | ||||
| 
 | ||||
| struct vpp_dev { | ||||
| 	int				id; | ||||
| 	struct platform_device		*pdev; | ||||
| 	spinlock_t			slock; | ||||
| 	struct media_pad		pad; | ||||
| 	struct exynos_md		*mdev; | ||||
| 	struct v4l2_subdev		*sd; | ||||
| 	void __iomem			*regs; | ||||
| 	unsigned long			state; | ||||
| 	struct clk			*gate_clk; | ||||
| 	struct vpp_resources		res; | ||||
| 	wait_queue_head_t		stop_queue; | ||||
| 	wait_queue_head_t		update_queue; | ||||
| 	struct timer_list		op_timer; | ||||
| 	u32				start_count; | ||||
| 	u32				done_count; | ||||
| 	u32				update_cnt; | ||||
| 	u32				update_cnt_prev; | ||||
| 	struct decon_win_config	*config; | ||||
| 	struct pm_qos_request		*vpp_disp_qos; | ||||
| 	struct pm_qos_request		*vpp_int_qos; | ||||
| 	struct pm_qos_request		vpp_mif_qos; | ||||
| 	u32				h_ratio; | ||||
| 	u32				v_ratio; | ||||
| 	struct vpp_fraction		fract_val; | ||||
| 	struct mutex			mlock; | ||||
| 	unsigned int			irq; | ||||
| 	u32				prev_read_order; | ||||
| 	u32				pbuf_num; | ||||
| 	u64				disp_cur_bw; | ||||
| 	u64				cur_bw; | ||||
| 	u64				prev_bw; | ||||
| 	u32				sc_w; | ||||
| 	u32				sc_h; | ||||
| 	struct decon_bts		*bts_ops; | ||||
| }; | ||||
| 
 | ||||
| extern struct vpp_dev *vpp0_for_decon; | ||||
| extern struct vpp_dev *vpp1_for_decon; | ||||
| extern struct vpp_dev *vpp2_for_decon; | ||||
| extern struct vpp_dev *vpp3_for_decon; | ||||
| extern struct vpp_dev *vpp4_for_decon; | ||||
| extern struct vpp_dev *vpp5_for_decon; | ||||
| extern struct vpp_dev *vpp6_for_decon; | ||||
| extern struct vpp_dev *vpp7_for_decon; | ||||
| extern struct vpp_dev *vpp8_for_decon; | ||||
| 
 | ||||
| static inline struct vpp_dev *get_vpp_drvdata(u32 id) | ||||
| { | ||||
| 	switch (id) { | ||||
| 	case 0: | ||||
| 		return vpp0_for_decon; | ||||
| 	case 1: | ||||
| 		return vpp1_for_decon; | ||||
| 	case 2: | ||||
| 		return vpp2_for_decon; | ||||
| 	case 3: | ||||
| 		return vpp3_for_decon; | ||||
| 	case 4: | ||||
| 		return vpp4_for_decon; | ||||
| 	case 5: | ||||
| 		return vpp5_for_decon; | ||||
| 	case 6: | ||||
| 		return vpp6_for_decon; | ||||
| 	case 7: | ||||
| 		return vpp7_for_decon; | ||||
| 	case 8: | ||||
| 		return vpp8_for_decon; | ||||
| 	default: | ||||
| 		return NULL; | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| static inline u32 vpp_read(u32 id, u32 reg_id) | ||||
| { | ||||
| 	struct vpp_dev *vpp = get_vpp_drvdata(id); | ||||
| 	return readl(vpp->regs + reg_id); | ||||
| } | ||||
| 
 | ||||
| static inline u32 vpp_read_mask(u32 id, u32 reg_id, u32 mask) | ||||
| { | ||||
| 	u32 val = vpp_read(id, reg_id); | ||||
| 	val &= (~mask); | ||||
| 	return val; | ||||
| } | ||||
| 
 | ||||
| static inline void vpp_write(u32 id, u32 reg_id, u32 val) | ||||
| { | ||||
| 	struct vpp_dev *vpp = get_vpp_drvdata(id); | ||||
| 	writel(val, vpp->regs + reg_id); | ||||
| } | ||||
| 
 | ||||
| static inline void vpp_write_mask(u32 id, u32 reg_id, u32 val, u32 mask) | ||||
| { | ||||
| 	struct vpp_dev *vpp = get_vpp_drvdata(id); | ||||
| 	u32 old = vpp_read(id, reg_id); | ||||
| 
 | ||||
| 	val = (val & mask) | (old & ~mask); | ||||
| 	writel(val, vpp->regs + reg_id); | ||||
| } | ||||
| 
 | ||||
| static inline void vpp_select_format(struct vpp_dev *vpp, struct vpp_img_format *vi) | ||||
| { | ||||
| 	struct decon_win_config *config = vpp->config; | ||||
| 
 | ||||
| 	vi->vgr = is_vgr(vpp); | ||||
| 	vi->normal = is_normal(vpp); | ||||
| 	vi->rot = is_rotation(config); | ||||
| 	vi->scale = is_scaling(vpp); | ||||
| 	vi->yuv = is_yuv(config); | ||||
| 	vi->yuv422 = is_yuv422(config); | ||||
| 	vi->yuv420 = is_yuv420(config); | ||||
| 	vi->pre_none = 1; | ||||
| 	vi->pre_12 = 0; | ||||
| 	vi->pre_14 = 0; | ||||
| 	vi->wb = is_wb(vpp); | ||||
| } | ||||
| 
 | ||||
| static inline void vpp_to_scale_params(struct vpp_dev *vpp, struct vpp_size_param *p) | ||||
| { | ||||
| 	struct decon_win_config *config = vpp->config; | ||||
| 	struct vpp_params *vpp_parm = &vpp->config->vpp_parm; | ||||
| 	struct vpp_fraction *fr = &vpp->fract_val; | ||||
| 
 | ||||
| 	p->src_x = config->src.x; | ||||
| 	p->src_y = config->src.y; | ||||
| 	p->src_w = config->src.w; | ||||
| 	p->src_h = config->src.h; | ||||
| 	p->fr_w = fr->w; | ||||
| 	p->fr_h = fr->h; | ||||
| 	p->dst_w = config->dst.w; | ||||
| 	p->dst_h = config->dst.h; | ||||
| 	p->vpp_h_ratio = vpp->h_ratio; | ||||
| 	p->vpp_v_ratio = vpp->v_ratio; | ||||
| 	p->src_fw = config->src.f_w; | ||||
| 	p->src_fh = config->src.f_h; | ||||
| 	p->fr_yx = vpp->fract_val.y_x; | ||||
| 	p->fr_yy = vpp->fract_val.y_y; | ||||
| 	p->fr_cx = vpp->fract_val.c_x; | ||||
| 	p->fr_cy = vpp->fract_val.c_y; | ||||
| 	p->rot = config->vpp_parm.rot; | ||||
| 	p->block_x = config->block_area.x; | ||||
| 	p->block_y = config->block_area.y; | ||||
| 	p->block_w = config->block_area.w; | ||||
| 	p->block_h = config->block_area.h; | ||||
| 	p->addr0 = vpp_parm->addr[0]; | ||||
| 	p->addr1 = vpp_parm->addr[1]; | ||||
| 	p->addr2 = vpp_parm->addr[2]; | ||||
| 
 | ||||
| } | ||||
| #endif | ||||
							
								
								
									
										263
									
								
								drivers/video/fbdev/exynos/decon_8890/vpp/vpp_coef.h
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										263
									
								
								drivers/video/fbdev/exynos/decon_8890/vpp/vpp_coef.h
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,263 @@ | |||
| /* linux/drivers/video/exynos/decon/vpp/vpp_coef.c
 | ||||
|  * | ||||
|  * Copyright (c) 2014 Samsung Electronics Co., Ltd. | ||||
|  *		http://www.samsung.com
 | ||||
|  * | ||||
|  * VPP poly-phase filter coefficients | ||||
|  * | ||||
|  * 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/types.h> | ||||
| #include "vpp.h" | ||||
| 
 | ||||
| /* 8-tap Filter Coefficient */ | ||||
| const s16 h_coef_8t[7][16][8] = { | ||||
| 	{	/* Ratio <= 65536 (~8:8) */ | ||||
| 		{  0,  0,   0, 128,   0,   0,  0,  0 },/* 0 */ | ||||
| 		{ -1,  2,  -6, 127,   7,  -2,  1,  0 },/* 1 */ | ||||
| 		{ -1,  4, -12, 125,  16,  -5,  1,  0 },/* 2 */ | ||||
| 		{ -1,  5, -15, 120,  25,  -8,  2,  0 },/* 3 */ | ||||
| 		{ -1,  6, -18, 114,  35, -10,  3, -1 },/* 4 */ | ||||
| 		{ -1,  6, -20, 107,  46, -13,  4, -1 },/* 5 */ | ||||
| 		{ -2,  7, -21,  99,  57, -16,  5, -1 },/* 6 */ | ||||
| 		{ -1,  6, -20,  89,  68, -18,  5, -1 },/* 7 */ | ||||
| 		{ -1,  6, -20,  79,  79, -20,  6, -1 },/* 8 */ | ||||
| 		{ -1,  5, -18,  68,  89, -20,  6, -1 },/* 9 */ | ||||
| 		{ -1,  5, -16,  57,  99, -21,  7, -2 },/* 10 */ | ||||
| 		{ -1,  4, -13,  46, 107, -20,  6, -1 },/* 11 */ | ||||
| 		{ -1,  3, -10,  35, 114, -18,  6, -1 },/* 12 */ | ||||
| 		{  0,  2,  -8,  25, 120, -15,  5, -1 },/* 13 */ | ||||
| 		{  0,  1,  -5,  16, 125, -12,  4, -1 },/* 14 */ | ||||
| 		{  0,  1,  -2,   7, 127,  -6,  2, -1 } /* 15 */ | ||||
| 	}, {	/* 65536 < Ratio <= 74898 (~8:7) */ | ||||
| 		{  3, -8,  14, 111,  13,  -8,  3,  0 },/* 0 */ | ||||
| 		{  2, -6,   7, 112,  21, -10,  3, -1 },/* 1 */ | ||||
| 		{  2, -4,   1, 110,  28, -12,  4, -1 },/* 2 */ | ||||
| 		{  1, -2,  -3, 106,  36, -13,  4, -1 },/* 3 */ | ||||
| 		{  1, -1,  -7, 103,  44, -15,  4, -1 },/* 4 */ | ||||
| 		{  1,  1, -11,  97,  53, -16,  4, -1 },/* 5 */ | ||||
| 		{  0,  2, -13,  91,  61, -16,  4, -1 },/* 6 */ | ||||
| 		{  0,  3, -15,  85,  69, -17,  4, -1 },/* 7 */ | ||||
| 		{  0,  3, -16,  77,  77, -16,  3,  0 },/* 8 */ | ||||
| 		{ -1,  4, -17,  69,  85, -15,  3,  0 },/* 9 */ | ||||
| 		{ -1,  4, -16,  61,  91, -13,  2,  0 },/* 10 */ | ||||
| 		{ -1,  4, -16,  53,  97, -11,  1,  1 },/* 11 */ | ||||
| 		{ -1,  4, -15,  44, 103,  -7, -1,  1 },/* 12 */ | ||||
| 		{ -1,  4, -13,  36, 106,  -3, -2,  1 },/* 13 */ | ||||
| 		{ -1,  4, -12,  28, 110,   1, -4,  2 },/* 14 */ | ||||
| 		{ -1,  3, -10,  21, 112,   7, -6,  2 } /* 15 */ | ||||
| 	}, {	/* 74898 < Ratio <= 87381 (~8:6) */ | ||||
| 		{ 2, -11,  25,  96, 25, -11,   2,  0 },/* 0 */ | ||||
| 		{ 2, -10,  19,  96, 31, -12,   2,  0 },/* 1 */ | ||||
| 		{ 2,  -9,  14,  94, 37, -12,   2,  0 },/* 2 */ | ||||
| 		{ 2,  -8,  10,  92, 43, -12,   1,  0 },/* 3 */ | ||||
| 		{ 2,  -7,   5,  90, 49, -12,   1,  0 },/* 4 */ | ||||
| 		{ 2,  -5,   1,  86, 55, -12,   0,  1 },/* 5 */ | ||||
| 		{ 2,  -4,  -2,  82, 61, -11,  -1,  1 },/* 6 */ | ||||
| 		{ 1,  -3,  -5,  77, 67,  -9,  -1,  1 },/* 7 */ | ||||
| 		{ 1,  -2,  -7,  72, 72,  -7,  -2,  1 },/* 8 */ | ||||
| 		{ 1,  -1,  -9,  67, 77,  -5,  -3,  1 },/* 9 */ | ||||
| 		{ 1,  -1, -11,  61, 82,  -2,  -4,  2 },/* 10 */ | ||||
| 		{ 1,   0, -12,  55, 86,   1,  -5,  2 },/* 11 */ | ||||
| 		{ 0,   1, -12,  49, 90,   5,  -7,  2 },/* 12 */ | ||||
| 		{ 0,   1, -12,  43, 92,  10,  -8,  2 },/* 13 */ | ||||
| 		{ 0,   2, -12,  37, 94,  14,  -9,  2 },/* 14 */ | ||||
| 		{ 0,   2, -12,  31, 96,  19, -10,  2 } /* 15 */ | ||||
| 	}, {	/* 87381 < Ratio <= 104857 (~8:5) */ | ||||
| 		{ -1,  -8, 33,  80, 33,  -8,  -1,  0 },/* 0 */ | ||||
| 		{ -1,  -8, 28,  80, 37,  -7,  -2,  1 },/* 1 */ | ||||
| 		{  0,  -8, 24,  79, 41,  -7,  -2,  1 },/* 2 */ | ||||
| 		{  0,  -8, 20,  78, 46,  -6,  -3,  1 },/* 3 */ | ||||
| 		{  0,  -8, 16,  76, 50,  -4,  -3,  1 },/* 4 */ | ||||
| 		{  0,  -7, 13,  74, 54,  -3,  -4,  1 },/* 5 */ | ||||
| 		{  1,  -7, 10,  71, 58,  -1,  -5,  1 },/* 6 */ | ||||
| 		{  1,  -6,  6,  68, 62,   1,  -5,  1 },/* 7 */ | ||||
| 		{  1,  -6,  4,  65, 65,   4,  -6,  1 },/* 8 */ | ||||
| 		{  1,  -5,  1,  62, 68,   6,  -6,  1 },/* 9 */ | ||||
| 		{  1,  -5, -1,  58, 71,  10,  -7,  1 },/* 10 */ | ||||
| 		{  1,  -4, -3,  54, 74,  13,  -7,  0 },/* 11 */ | ||||
| 		{  1,  -3, -4,  50, 76,  16,  -8,  0 },/* 12 */ | ||||
| 		{  1,  -3, -6,  46, 78,  20,  -8,  0 },/* 13 */ | ||||
| 		{  1,  -2, -7,  41, 79,  24,  -8,  0 },/* 14 */ | ||||
| 		{  1,  -2, -7,  37, 80,  28,  -8, -1 } /* 15 */ | ||||
| 	}, {	/* 104857 < Ratio <= 131072 (~8:4) */ | ||||
| 		{ -3,   0, 35,  64, 35,   0,  -3,  0 },/* 0 */ | ||||
| 		{ -3,  -1, 32,  64, 38,   1,  -3,  0 },/* 1 */ | ||||
| 		{ -2,  -2, 29,  63, 41,   2,  -3,  0 },/* 2 */ | ||||
| 		{ -2,  -3, 27,  63, 43,   4,  -4,  0 },/* 3 */ | ||||
| 		{ -2,  -3, 24,  61, 46,   6,  -4,  0 },/* 4 */ | ||||
| 		{ -2,  -3, 21,  60, 49,   7,  -4,  0 },/* 5 */ | ||||
| 		{ -1,  -4, 19,  59, 51,   9,  -4, -1 },/* 6 */ | ||||
| 		{ -1,  -4, 16,  57, 53,  12,  -4, -1 },/* 7 */ | ||||
| 		{ -1,  -4, 14,  55, 55,  14,  -4, -1 },/* 8 */ | ||||
| 		{ -1,  -4, 12,  53, 57,  16,  -4, -1 },/* 9 */ | ||||
| 		{ -1,  -4,  9,  51, 59,  19,  -4, -1 },/* 10 */ | ||||
| 		{  0,  -4,  7,  49, 60,  21,  -3, -2 },/* 11 */ | ||||
| 		{  0,  -4,  6,  46, 61,  24,  -3, -2 },/* 12 */ | ||||
| 		{  0,  -4,  4,  43, 63,  27,  -3, -2 },/* 13 */ | ||||
| 		{  0,  -3,  2,  41, 63,  29,  -2, -2 },/* 14 */ | ||||
| 		{  0,  -3,  1,  38, 64,  32,  -1, -3 } /* 15 */ | ||||
| 	}, {	/* 131072 < Ratio <= 174762 (~8:3) */ | ||||
| 		{ -1,   8, 33,  48, 33,   8,  -1,  0 },/* 0 */ | ||||
| 		{ -1,   7, 31,  49, 35,   9,  -1, -1 },/* 1 */ | ||||
| 		{ -1,   6, 30,  49, 36,  10,  -1, -1 },/* 2 */ | ||||
| 		{ -1,   5, 28,  48, 38,  12,  -1, -1 },/* 3 */ | ||||
| 		{ -1,   4, 26,  48, 39,  13,   0, -1 },/* 4 */ | ||||
| 		{ -1,   3, 24,  47, 41,  15,   0, -1 },/* 5 */ | ||||
| 		{ -1,   2, 23,  47, 42,  16,   0, -1 },/* 6 */ | ||||
| 		{ -1,   2, 21,  45, 43,  18,   1, -1 },/* 7 */ | ||||
| 		{ -1,   1, 19,  45, 45,  19,   1, -1 },/* 8 */ | ||||
| 		{ -1,   1, 18,  43, 45,  21,   2, -1 },/* 9 */ | ||||
| 		{ -1,   0, 16,  42, 47,  23,   2, -1 },/* 10 */ | ||||
| 		{ -1,   0, 15,  41, 47,  24,   3, -1 },/* 11 */ | ||||
| 		{ -1,   0, 13,  39, 48,  26,   4, -1 },/* 12 */ | ||||
| 		{ -1,  -1, 12,  38, 48,  28,   5, -1 },/* 13 */ | ||||
| 		{ -1,  -1, 10,  36, 49,  30,   6, -1 },/* 14 */ | ||||
| 		{ -1,  -1,  9,  35, 49,  31,   7, -1 } /* 15 */ | ||||
| 	}, {	/* 174762 < Ratio <= 262144 (~8:2) */ | ||||
| 		{  2,  13, 30,  38, 30,  13,   2,  0 },/* 0 */ | ||||
| 		{  2,  12, 29,  38, 30,  14,   3,  0 },/* 1 */ | ||||
| 		{  2,  11, 28,  38, 31,  15,   3,  0 },/* 2 */ | ||||
| 		{  2,  10, 26,  38, 32,  16,   4,  0 },/* 3 */ | ||||
| 		{  1,  10, 26,  37, 33,  17,   4,  0 },/* 4 */ | ||||
| 		{  1,   9, 24,  37, 34,  18,   5,  0 },/* 5 */ | ||||
| 		{  1,   8, 24,  37, 34,  19,   5,  0 },/* 6 */ | ||||
| 		{  1,   7, 22,  36, 35,  20,   6,  1 },/* 7 */ | ||||
| 		{  1,   6, 21,  36, 36,  21,   6,  1 },/* 8 */ | ||||
| 		{  1,   6, 20,  35, 36,  22,   7,  1 },/* 9 */ | ||||
| 		{  0,   5, 19,  34, 37,  24,   8,  1 },/* 10 */ | ||||
| 		{  0,   5, 18,  34, 37,  24,   9,  1 },/* 11 */ | ||||
| 		{  0,   4, 17,  33, 37,  26,  10,  1 },/* 12 */ | ||||
| 		{  0,   4, 16,  32, 38,  26,  10,  2 },/* 13 */ | ||||
| 		{  0,   3, 15,  31, 38,  28,  11,  2 },/* 14 */ | ||||
| 		{  0,   3, 14,  30, 38,  29,  12,  2 } /* 15 */ | ||||
| 	} | ||||
| }; | ||||
| 
 | ||||
| /* 4-tap Filter Coefficient */ | ||||
| const s16 v_coef_4t[7][16][4] = { | ||||
| 	{	/* Ratio <= 65536 (~8:8) */ | ||||
| 		{  0, 128,   0,  0 },/* 0 */ | ||||
| 		{ -4, 127,   5,  0 },/* 1 */ | ||||
| 		{ -6, 124,  11, -1 },/* 2 */ | ||||
| 		{ -8, 118,  19, -1 },/* 3 */ | ||||
| 		{ -8, 111,  27, -2 },/* 4 */ | ||||
| 		{ -8, 102,  37, -3 },/* 5 */ | ||||
| 		{ -8,  92,  48, -4 },/* 6 */ | ||||
| 		{ -7,  81,  59, -5 },/* 7 */ | ||||
| 		{ -6,  70,  70, -6 },/* 8 */ | ||||
| 		{ -5,  59,  81, -7 },/* 9 */ | ||||
| 		{ -4,  48,  92, -8 },/* 10 */ | ||||
| 		{ -3,  37, 102, -8 },/* 11 */ | ||||
| 		{ -2,  27, 111, -8 },/* 12 */ | ||||
| 		{ -1,  19, 118, -8 },/* 13 */ | ||||
| 		{ -1,  11, 124, -6 },/* 14 */ | ||||
| 		{  0,   5, 127, -4 } /* 15 */ | ||||
| 	}, {	/* 65536 < Ratio <= 74898 (~8:7) */ | ||||
| 		{  8, 112,   8,  0 },/* 0 */ | ||||
| 		{  4, 111,  14, -1 },/* 1 */ | ||||
| 		{  1, 109,  20, -2 },/* 2 */ | ||||
| 		{ -2, 105,  27, -2 },/* 3 */ | ||||
| 		{ -3, 100,  34, -3 },/* 4 */ | ||||
| 		{ -5,  93,  43, -3 },/* 5 */ | ||||
| 		{ -5,  86,  51, -4 },/* 6 */ | ||||
| 		{ -5,  77,  60, -4 },/* 7 */ | ||||
| 		{ -5,  69,  69, -5 },/* 8 */ | ||||
| 		{ -4,  60,  77, -5 },/* 9 */ | ||||
| 		{ -4,  51,  86, -5 },/* 10 */ | ||||
| 		{ -3,  43,  93, -5 },/* 11 */ | ||||
| 		{ -3,  34, 100, -3 },/* 12 */ | ||||
| 		{ -2,  27, 105, -2 },/* 13 */ | ||||
| 		{ -2,  20, 109,  1 },/* 14 */ | ||||
| 		{ -1,  14, 111,  4 } /* 15 */ | ||||
| 	}, {	/* 74898 < Ratio <= 87381 (~8:6) */ | ||||
| 		{ 16,  96,  16,  0 },/* 0 */ | ||||
| 		{ 12,  97,  21, -2 },/* 1 */ | ||||
| 		{  8,  96,  26, -2 },/* 2 */ | ||||
| 		{  5,  93,  32, -2 },/* 3 */ | ||||
| 		{  2,  89,  39, -2 },/* 4 */ | ||||
| 		{  0,  84,  46, -2 },/* 5 */ | ||||
| 		{ -1,  79,  53, -3 },/* 6 */ | ||||
| 		{ -2,  73,  59, -2 },/* 7 */ | ||||
| 		{ -2,  66,  66, -2 },/* 8 */ | ||||
| 		{ -2,  59,  73, -2 },/* 9 */ | ||||
| 		{ -3,  53,  79, -1 },/* 10 */ | ||||
| 		{ -2,  46,  84,  0 },/* 11 */ | ||||
| 		{ -2,  39,  89,  2 },/* 12 */ | ||||
| 		{ -2,  32,  93,  5 },/* 13 */ | ||||
| 		{ -2,  26,  96,  8 },/* 14 */ | ||||
| 		{ -2,  21,  97, 12 } /* 15 */ | ||||
| 	}, {	/* 87381 < Ratio <= 104857 (~8:5) */ | ||||
| 		{ 22,  84,  22,  0 },/* 0 */ | ||||
| 		{ 18,  85,  26, -1 },/* 1 */ | ||||
| 		{ 14,  84,  31, -1 },/* 2 */ | ||||
| 		{ 11,  82,  36, -1 },/* 3 */ | ||||
| 		{  8,  79,  42, -1 },/* 4 */ | ||||
| 		{  6,  76,  47, -1 },/* 5 */ | ||||
| 		{  4,  72,  52,  0 },/* 6 */ | ||||
| 		{  2,  68,  58,  0 },/* 7 */ | ||||
| 		{  1,  63,  63,  1 },/* 8 */ | ||||
| 		{  0,  58,  68,  2 },/* 9 */ | ||||
| 		{  0,  52,  72,  4 },/* 10 */ | ||||
| 		{ -1,  47,  76,  6 },/* 11 */ | ||||
| 		{ -1,  42,  79,  8 },/* 12 */ | ||||
| 		{ -1,  36,  82, 11 },/* 13 */ | ||||
| 		{ -1,  31,  84, 14 },/* 14 */ | ||||
| 		{ -1,  26,  85, 18 } /* 15 */ | ||||
| 	}, {	/* 104857 < Ratio <= 131072 (~8:4) */ | ||||
| 		{ 26,  76,  26,  0 },/* 0 */ | ||||
| 		{ 22,  76,  30,  0 },/* 1 */ | ||||
| 		{ 19,  75,  34,  0 },/* 2 */ | ||||
| 		{ 16,  73,  38,  1 },/* 3 */ | ||||
| 		{ 13,  71,  43,  1 },/* 4 */ | ||||
| 		{ 10,  69,  47,  2 },/* 5 */ | ||||
| 		{  8,  66,  51,  3 },/* 6 */ | ||||
| 		{  6,  63,  55,  4 },/* 7 */ | ||||
| 		{  5,  59,  59,  5 },/* 8 */ | ||||
| 		{  4,  55,  63,  6 },/* 9 */ | ||||
| 		{  3,  51,  66,  8 },/* 10 */ | ||||
| 		{  2,  47,  69, 10 },/* 11 */ | ||||
| 		{  1,  43,  71, 13 },/* 12 */ | ||||
| 		{  1,  38,  73, 16 },/* 13 */ | ||||
| 		{  0,  34,  75, 19 },/* 14 */ | ||||
| 		{  0,  30,  76, 22 } /* 15 */ | ||||
| 	}, {	/* 131072 < Ratio <= 174762 (~8:3) */ | ||||
| 		{ 29,  70,  29,  0 },/* 0 */ | ||||
| 		{ 26,  68,  32,  2 },/* 1 */ | ||||
| 		{ 23,  67,  36,  2 },/* 2 */ | ||||
| 		{ 20,  66,  39,  3 },/* 3 */ | ||||
| 		{ 17,  65,  43,  3 },/* 4 */ | ||||
| 		{ 15,  63,  46,  4 },/* 5 */ | ||||
| 		{ 12,  61,  50,  5 },/* 6 */ | ||||
| 		{ 10,  58,  53,  7 },/* 7 */ | ||||
| 		{  8,  56,  56,  8 },/* 8 */ | ||||
| 		{  7,  53,  58, 10 },/* 9 */ | ||||
| 		{  5,  50,  61, 12 },/* 10 */ | ||||
| 		{  4,  46,  63, 15 },/* 11 */ | ||||
| 		{  3,  43,  65, 17 },/* 12 */ | ||||
| 		{  3,  39,  66, 20 },/* 13 */ | ||||
| 		{  2,  36,  67, 23 },/* 14 */ | ||||
| 		{  2,  32,  68, 26 } /* 15 */ | ||||
| 	}, {	/* 174762 < Ratio <= 262144 (~8:2) */ | ||||
| 		{ 32,  64,  32,  0 },/* 0 */ | ||||
| 		{ 28,  63,  34,  3 },/* 1 */ | ||||
| 		{ 25,  62,  37,  4 },/* 2 */ | ||||
| 		{ 22,  62,  40,  4 },/* 3 */ | ||||
| 		{ 19,  61,  43,  5 },/* 4 */ | ||||
| 		{ 17,  59,  46,  6 },/* 5 */ | ||||
| 		{ 15,  58,  48,  7 },/* 6 */ | ||||
| 		{ 13,  55,  51,  9 },/* 7 */ | ||||
| 		{ 11,  53,  53, 11 },/* 8 */ | ||||
| 		{  9,  51,  55, 13 },/* 9 */ | ||||
| 		{  7,  48,  58, 15 },/* 10 */ | ||||
| 		{  6,  46,  59, 17 },/* 11 */ | ||||
| 		{  5,  43,  61, 19 },/* 12 */ | ||||
| 		{  4,  40,  62, 22 },/* 13 */ | ||||
| 		{  4,  37,  62, 25 },/* 14 */ | ||||
| 		{  3,  34,  63, 28 } /* 15 */ | ||||
| 	} | ||||
| }; | ||||
							
								
								
									
										226
									
								
								drivers/video/fbdev/exynos/decon_8890/vpp/vpp_common.h
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										226
									
								
								drivers/video/fbdev/exynos/decon_8890/vpp/vpp_common.h
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,226 @@ | |||
| /*
 | ||||
|  * Copyright (c) 2015 Samsung Electronics Co., Ltd. | ||||
|  *		http://www.samsung.com
 | ||||
|  * | ||||
|  * Header file for Exynos VPP driver | ||||
|  * | ||||
|  * 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. | ||||
| */ | ||||
| 
 | ||||
| #ifndef ___SAMSUNG_VPP_COMMON_H__ | ||||
| #define ___SAMSUNG_VPP_COMMON_H__ | ||||
| 
 | ||||
| #define YUV_SRC_OFFSET_MULTIPLE	2 | ||||
| #define YUV_SRC_SIZE_MULTIPLE	2 | ||||
| #define YUV_SRC_SIZE_MUL_HEIGHT	1 | ||||
| #define YUV_SRC_WIDTH_MAX	65534 | ||||
| #define YUV_SRC_HEIGHT_MAX	8190 | ||||
| #define YUV_SRC_WIDTH_MIN	32 | ||||
| #define YUV_SRC_HEIGHT_MIN	16 | ||||
| #define RGB_SRC_OFFSET_MULTIPLE	1 | ||||
| #define RGB_SRC_SIZE_MULTIPLE	1 | ||||
| #define RGB_SRC_WIDTH_MAX	65535 | ||||
| #define RGB_SRC_HEIGHT_MAX	8191 | ||||
| #define RGB_SRC_WIDTH_MIN	16 | ||||
| #define RGB_SRC_HEIGHT_MIN	8 | ||||
| 
 | ||||
| #define ROT1_RGB_SRC_WIDTH_MIN	32 | ||||
| #define ROT1_RGB_SRC_HEIGHT_MIN	16 | ||||
| #define ROT1_YUV_SRC_WIDTH_MIN	64 | ||||
| #define ROT1_YUV_SRC_HEIGHT_MIN	32 | ||||
| #define ROT2_RGB_SRC_WIDTH_MIN	16 | ||||
| #define ROT2_RGB_SRC_HEIGHT_MIN	32 | ||||
| #define ROT2_YUV_SRC_WIDTH_MIN	32 | ||||
| #define ROT2_YUV_SRC_HEIGHT_MIN	64 | ||||
| 
 | ||||
| #define YUV_IMG_SIZE_MULTIPLE	2 | ||||
| #define RGB_IMG_SIZE_MULTIPLE	1 | ||||
| #define IMG_WIDTH_MAX		4096 | ||||
| #define IMG_HEIGHT_MAX		4096 | ||||
| #define RGB_IMG_WIDTH_MIN	16 | ||||
| #define RGB_IMG_HEIGHT_MIN	8 | ||||
| #define YUV_IMG_WIDTH_MIN	32 | ||||
| #define YUV_IMG_HEIGHT_MIN	16 | ||||
| 
 | ||||
| #define IMG_SIZE_MULTIPLE	2 | ||||
| 
 | ||||
| #define ROT1_RGB_IMG_WIDTH_MIN	32 | ||||
| #define ROT1_RGB_IMG_HEIGHT_MIN	16 | ||||
| #define ROT1_YUV_IMG_WIDTH_MIN	64 | ||||
| #define ROT1_YUV_IMG_HEIGHT_MIN	32 | ||||
| #define ROT2_RGB_IMG_WIDTH_MIN	16 | ||||
| #define ROT2_RGB_IMG_HEIGHT_MIN	32 | ||||
| #define ROT2_YUV_IMG_WIDTH_MIN	32 | ||||
| #define ROT2_YUV_IMG_HEIGHT_MIN	64 | ||||
| 
 | ||||
| #define ROT3_RGB_IMG_WIDTH_MAX	4096 | ||||
| #define ROT3_RGB_IMG_HEIGHT_MAX	4096 | ||||
| #define ROT3_YUV_IMG_WIDTH_MAX	4096 | ||||
| #define ROT3_YUV_IMG_HEIGHT_MAX	4096 | ||||
| #define ROT4_RGB_IMG_WIDTH_MAX	2048 | ||||
| #define ROT4_RGB_IMG_HEIGHT_MAX	2048 | ||||
| #define ROT4_YUV_IMG_WIDTH_MAX	2048 | ||||
| #define ROT4_YUV_IMG_HEIGHT_MAX	2048 | ||||
| 
 | ||||
| #define BLK_WIDTH_MAX		4096 | ||||
| #define BLK_HEIGHT_MAX		4096 | ||||
| #define BLK_WIDTH_MIN		144 | ||||
| #define BLK_HEIGHT_MIN		10 | ||||
| #define ROT3_RGB_BLK_WIDTH_MAX	4096 | ||||
| #define ROT3_RGB_BLK_HEIGHT_MAX	4096 | ||||
| #define ROT3_RGB_BLK_WIDTH_MIN	128 | ||||
| #define ROT3_RGB_BLK_HEIGHT_MIN	16 | ||||
| #define ROT4_RGB_BLK_WIDTH_MAX	2048 | ||||
| #define ROT4_RGB_BLK_HEIGHT_MAX	2048 | ||||
| 
 | ||||
| #define SCALED_SIZE_MULTIPLE	1 | ||||
| #define SCALED_WIDTH_MAX	4096 | ||||
| #define SCALED_HEIGHT_MAX	4096 | ||||
| #define SCALED_WIDTH_MIN	16 | ||||
| #define SCALED_HEIGHT_MIN	8 | ||||
| 
 | ||||
| #define PRE_RGB_WIDTH		1 | ||||
| #define PRE_RGB_HEIGHT		1 | ||||
| #define PRE_YUV_WIDTH		2 | ||||
| #define PRE_YUV_HEIGHT		2 | ||||
| #define PRE_ROT1_YUV_HEIGHT	1 | ||||
| #define PRE12_RGB_WIDTH		2 | ||||
| #define PRE12_RGB_HEIGHT	2 | ||||
| #define PRE12_YUV_WIDTH		4 | ||||
| #define PRE12_ROT1_YUV_HEIGHT	2 | ||||
| #define PRE12_YUV_HEIGHT	4 | ||||
| #define PRE14_RGB_WIDTH		4 | ||||
| #define PRE14_RGB_HEIGHT	4 | ||||
| #define PRE14_YUV_WIDTH		8 | ||||
| #define PRE14_YUV_HEIGHT	8 | ||||
| #define PRE14_ROT1_YUV_HEIGHT	4 | ||||
| 
 | ||||
| #define SRC_SIZE_MULTIPLE	2 | ||||
| #define SRC_ROT1_MUL_Y		1 | ||||
| #define SRC_ROT2_MUL_Y		2 | ||||
| 
 | ||||
| #define DST_SIZE_MULTIPLE	1 | ||||
| #define DST_SIZE_WIDTH_MIN	16 | ||||
| #define DST_SIZE_WIDTH_MAX	8191 | ||||
| #define DST_SIZE_HEIGHT_MIN	8 | ||||
| #define DST_SIZE_HEIGHT_MAX	8191 | ||||
| #define DST_OFFSET_MULTIPLE	1 | ||||
| #define DST_IMGAGE_MULTIPLE	1 | ||||
| #define DST_IMG_WIDTH_MIN	16 | ||||
| #define DST_IMG_HEIGHT_MIN	8 | ||||
| #define DST_IMG_MAX		4096 | ||||
| 
 | ||||
| struct vpp_size_constraints { | ||||
| 	u32		src_mul_w; | ||||
| 	u32		src_mul_h; | ||||
| 	u32		src_w_min; | ||||
| 	u32		src_w_max; | ||||
| 	u32		src_h_min; | ||||
| 	u32		src_h_max; | ||||
| 	u32		img_mul_w; | ||||
| 	u32		img_mul_h; | ||||
| 	u32		img_w_min; | ||||
| 	u32		img_w_max; | ||||
| 	u32		img_h_min; | ||||
| 	u32		img_h_max; | ||||
| 	u32		blk_w_min; | ||||
| 	u32		blk_w_max; | ||||
| 	u32		blk_h_min; | ||||
| 	u32		blk_h_max; | ||||
| 	u32		blk_mul_w; | ||||
| 	u32		blk_mul_h; | ||||
| 	u32		src_mul_x; | ||||
| 	u32		src_mul_y; | ||||
| 	u32		sca_w_min; | ||||
| 	u32		sca_w_max; | ||||
| 	u32		sca_h_min; | ||||
| 	u32		sca_h_max; | ||||
| 	u32		sca_mul_w; | ||||
| 	u32		sca_mul_h; | ||||
| 	u32		dst_mul_w; | ||||
| 	u32		dst_mul_h; | ||||
| 	u32		dst_w_min; | ||||
| 	u32		dst_w_max; | ||||
| 	u32		dst_h_min; | ||||
| 	u32		dst_h_max; | ||||
| 	u32		dst_mul_x; | ||||
| 	u32		dst_mul_y; | ||||
| }; | ||||
| 
 | ||||
| struct vpp_img_format { | ||||
| 	u32		vgr; | ||||
| 	u32		normal; | ||||
| 	u32		pre_none; | ||||
| 	u32		pre_12; | ||||
| 	u32		pre_14; | ||||
| 	u32		rot; | ||||
| 	u32		scale; | ||||
| 	u32		yuv; | ||||
| 	u32		yuv422; | ||||
| 	u32		yuv420; | ||||
| 	u32		wb; | ||||
| }; | ||||
| 
 | ||||
| struct vpp_size_param { | ||||
| 	u32		src_x; | ||||
| 	u32		src_y; | ||||
| 	u32		src_fw; | ||||
| 	u32		src_fh; | ||||
| 	u32		src_w; | ||||
| 	u32		src_h; | ||||
| 	u32		dst_w; | ||||
| 	u32		dst_h; | ||||
| 	u32		fr_w; | ||||
| 	u32		fr_h; | ||||
| 	u32		fr_yx; | ||||
| 	u32		fr_yy; | ||||
| 	u32		fr_cx; | ||||
| 	u32		fr_cy; | ||||
| 	u32		vpp_h_ratio; | ||||
| 	u32		vpp_v_ratio; | ||||
| 	u32		rot; | ||||
| 	u32		block_w; | ||||
| 	u32		block_h; | ||||
| 	u32		block_x; | ||||
| 	u32		block_y; | ||||
| 	u64		addr0; | ||||
| 	u64		addr1; | ||||
| 	u64		addr2; | ||||
| }; | ||||
| 
 | ||||
| /* CAL APIs list */ | ||||
| void vpp_reg_set_realtime_path(u32 id); | ||||
| void vpp_reg_set_framedone_irq(u32 id, u32 enable); | ||||
| void vpp_reg_set_deadlock_irq(u32 id, u32 enable); | ||||
| void vpp_reg_set_read_slave_err_irq(u32 id, u32 enable); | ||||
| void vpp_reg_set_sfr_update_done_irq(u32 id, u32 enable); | ||||
| void vpp_reg_set_hw_reset_done_mask(u32 id, u32 enable); | ||||
| void vpp_reg_set_lookup_table(u32 id); | ||||
| void vpp_reg_set_enable_interrupt(u32 id); | ||||
| void vpp_reg_set_rgb_type(u32 id, u32 type); | ||||
| void vpp_reg_set_dynamic_clock_gating(u32 id); | ||||
| void vpp_reg_set_plane_alpha_fixed(u32 id); | ||||
| 
 | ||||
| /* CAL raw functions list */ | ||||
| int vpp_reg_set_sw_reset(u32 id); | ||||
| void vpp_reg_set_in_size(u32 id, struct vpp_size_param *p); | ||||
| void vpp_reg_set_out_size(u32 id, u32 dst_w, u32 dst_h); | ||||
| void vpp_reg_set_scale_ratio(u32 id, struct vpp_size_param *p, u32 rot_en); | ||||
| int vpp_reg_set_in_format(u32 id, u32 format, struct vpp_img_format *vi); | ||||
| void vpp_reg_set_in_block_size(u32 id, u32 enable, struct vpp_size_param *p); | ||||
| void vpp_reg_set_in_buf_addr(u32 id, struct vpp_size_param *p); | ||||
| void vpp_reg_set_smart_if_pix_num(u32 id, u32 dst_w, u32 dst_h); | ||||
| void vpp_reg_set_sfr_update_force(u32 id); | ||||
| int vpp_reg_wait_op_status(u32 id); | ||||
| int vpp_reg_set_rotation(u32 id, struct vpp_size_param *p); | ||||
| void vpp_reg_set_plane_alpha(u32 id, u32 plane_alpha); | ||||
| void vpp_reg_wait_idle(u32 id); | ||||
| int vpp_reg_get_irq_status(u32 id); | ||||
| void vpp_reg_set_clear_irq(u32 id, u32 irq); | ||||
| void vpp_constraints_params(struct vpp_size_constraints *vc, struct vpp_img_format *vi); | ||||
| void vpp_reg_init(u32 id); | ||||
| void vpp_reg_deinit(u32 id, u32 reset_en); | ||||
| void vpp_reg_wait_pingpong_clear(u32 id); | ||||
| #endif /* ___SAMSUNG_VPP_COMMON_H__ */ | ||||
							
								
								
									
										1051
									
								
								drivers/video/fbdev/exynos/decon_8890/vpp/vpp_drv.c
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										1051
									
								
								drivers/video/fbdev/exynos/decon_8890/vpp/vpp_drv.c
									
										
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load diff
											
										
									
								
							
							
								
								
									
										671
									
								
								drivers/video/fbdev/exynos/decon_8890/vpp/vpp_reg_8890.c
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										671
									
								
								drivers/video/fbdev/exynos/decon_8890/vpp/vpp_reg_8890.c
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,671 @@ | |||
| /* linux/drivers/video/exynos/decon/vpp/vpp_regs.c
 | ||||
|  * | ||||
|  * Copyright (c) 2011 Samsung Electronics Co., Ltd. | ||||
|  *		http://www.samsung.com
 | ||||
|  * | ||||
|  * Samsung EXYNOS5 SoC series G-scaler driver | ||||
|  * | ||||
|  * 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/io.h> | ||||
| #include <linux/delay.h> | ||||
| #include <linux/ktime.h> | ||||
| #include "vpp.h" | ||||
| #include "vpp_common.h" | ||||
| #include "vpp_coef.h" | ||||
| 
 | ||||
| #define VPP_SC_RATIO_MAX	((1 << 20) * 8 / 8) | ||||
| #define VPP_SC_RATIO_7_8	((1 << 20) * 8 / 7) | ||||
| #define VPP_SC_RATIO_6_8	((1 << 20) * 8 / 6) | ||||
| #define VPP_SC_RATIO_5_8	((1 << 20) * 8 / 5) | ||||
| #define VPP_SC_RATIO_4_8	((1 << 20) * 8 / 4) | ||||
| #define VPP_SC_RATIO_3_8	((1 << 20) * 8 / 3) | ||||
| 
 | ||||
| int vpp_reg_wait_op_status(u32 id) | ||||
| { | ||||
| 	u32 cfg = 0; | ||||
| 
 | ||||
| 	unsigned long cnt = 100000; | ||||
| 
 | ||||
| 	do { | ||||
| 		cfg = vpp_read(id, VG_ENABLE); | ||||
| 		if (!(cfg & (VG_ENABLE_OP_STATUS))) | ||||
| 			return 0; | ||||
| 		udelay(10); | ||||
| 	} while (--cnt); | ||||
| 
 | ||||
| 	vpp_err("timeout op_status to idle\n"); | ||||
| 
 | ||||
| 	return -EBUSY; | ||||
| } | ||||
| 
 | ||||
| void vpp_reg_wait_idle(u32 id) | ||||
| { | ||||
| 	u32 cfg = 0; | ||||
| 
 | ||||
| 	unsigned long cnt = 100000; | ||||
| 
 | ||||
| 	do { | ||||
| 		cfg = vpp_read(id, VG_ENABLE); | ||||
| 		if (!(cfg & (VG_ENABLE_OP_STATUS))) | ||||
| 			return; | ||||
| 		vpp_info("vpp%d is operating...\n", id); | ||||
| 		udelay(10); | ||||
| 	} while (--cnt); | ||||
| 
 | ||||
| 	vpp_err("timeout op_status to idle\n"); | ||||
| } | ||||
| 
 | ||||
| int vpp_reg_set_sw_reset(u32 id) | ||||
| { | ||||
| 	u32 cfg = 0; | ||||
| 
 | ||||
| 	unsigned long cnt = 100000; | ||||
| 	vpp_write_mask(id, VG_ENABLE, ~0, VG_ENABLE_SRESET); | ||||
| 
 | ||||
| 	do { | ||||
| 		cfg = vpp_read(id, VG_ENABLE); | ||||
| 		if (!(cfg & (VG_ENABLE_SRESET))) | ||||
| 			return 0; | ||||
| 		udelay(10); | ||||
| 	} while (--cnt); | ||||
| 
 | ||||
| 	vpp_err("timeout sw reset\n"); | ||||
| 
 | ||||
| 	return -EBUSY; | ||||
| } | ||||
| 
 | ||||
| void vpp_reg_wait_pingpong_clear(u32 id) | ||||
| { | ||||
| 	u32 cfg = 0; | ||||
| 	unsigned long cnt = 1700; | ||||
| 
 | ||||
| 	do { | ||||
| 		cfg = vpp_read(id, VG_PINGPONG_UPDATE); | ||||
| 		if (!(cfg & (VG_ADDR_PINGPONG_UPDATE))) | ||||
| 			return; | ||||
| 		udelay(10); | ||||
| 	} while (--cnt); | ||||
| 	vpp_err("timeout of VPP(%d) pingpong_clear\n", id); | ||||
| } | ||||
| 
 | ||||
| void vpp_reg_set_realtime_path(u32 id) | ||||
| { | ||||
| 	vpp_write_mask(id, VG_ENABLE, ~0, VG_ENABLE_RT_PATH_EN); | ||||
| } | ||||
| 
 | ||||
| void vpp_reg_set_framedone_irq(u32 id, u32 enable) | ||||
| { | ||||
| 	u32 val = enable ? ~0 : 0; | ||||
| 	vpp_write_mask(id, VG_IRQ, val, VG_IRQ_FRAMEDONE_MASK); | ||||
| } | ||||
| 
 | ||||
| void vpp_reg_set_deadlock_irq(u32 id, u32 enable) | ||||
| { | ||||
| 	u32 val = enable ? ~0 : 0; | ||||
| 	vpp_write_mask(id, VG_IRQ, val, VG_IRQ_DEADLOCK_STATUS_MASK); | ||||
| } | ||||
| 
 | ||||
| void vpp_reg_set_read_slave_err_irq(u32 id, u32 enable) | ||||
| { | ||||
| 	u32 val = enable ? ~0 : 0; | ||||
| 	vpp_write_mask(id, VG_IRQ, val, VG_IRQ_READ_SLAVE_ERROR_MASK); | ||||
| } | ||||
| 
 | ||||
| void vpp_reg_set_sfr_update_done_irq(u32 id, u32 enable) | ||||
| { | ||||
| 	u32 val = enable ? ~0 : 0; | ||||
| 	vpp_write_mask(id, VG_IRQ, val, VG_IRQ_SFR_UPDATE_DONE_MASK); | ||||
| } | ||||
| 
 | ||||
| void vpp_reg_set_sfr_update_force(u32 id) | ||||
| { | ||||
| 	vpp_write_mask(id, VG_ENABLE, ~0, VG_ENABLE_SFR_UPDATE_FORCE); | ||||
| } | ||||
| 
 | ||||
| void vpp_reg_set_enable_interrupt(u32 id) | ||||
| { | ||||
| 	vpp_write_mask(id, VG_IRQ, ~0, VG_IRQ_ENABLE); | ||||
| } | ||||
| 
 | ||||
| void vpp_reg_set_hw_reset_done_mask(u32 id, u32 enable) | ||||
| { | ||||
| 	u32 val = enable ? ~0 : 0; | ||||
| 	vpp_write_mask(id, VG_IRQ, val, VG_IRQ_HW_RESET_DONE_MASK); | ||||
| } | ||||
| 
 | ||||
| int vpp_reg_set_in_format(u32 id, u32 format, struct vpp_img_format *vi) | ||||
| { | ||||
| 	u32 cfg = vpp_read(id, VG_IN_CON); | ||||
| 
 | ||||
| 	cfg &= ~(VG_IN_CON_IMG_FORMAT_MASK | | ||||
| 			VG_IN_CON_CHROMINANCE_STRIDE_EN); | ||||
| 
 | ||||
| 	if ((id == 0 || id == 1 || id == 4 || id == 5) && | ||||
| 			(format >= DECON_PIXEL_FORMAT_NV16)) { | ||||
| 		vpp_err("Unsupported YUV format in G%d \n", id); | ||||
| 		return -EINVAL; | ||||
| 	} | ||||
| 
 | ||||
| 	if (!vi->vgr && (vi->scale || vi->rot)) { | ||||
| 		vpp_err("Unsupported Scailing in (V)G%d \n", id); | ||||
| 		return -EINVAL; | ||||
| 	} | ||||
| 
 | ||||
| 	switch (format) { | ||||
| 	case DECON_PIXEL_FORMAT_ARGB_8888: | ||||
| 		cfg |= VG_IN_CON_IMG_FORMAT_ARGB8888; | ||||
| 		break; | ||||
| 	case DECON_PIXEL_FORMAT_ABGR_8888: | ||||
| 		cfg |= VG_IN_CON_IMG_FORMAT_ABGR8888; | ||||
| 		break; | ||||
| 	case DECON_PIXEL_FORMAT_RGBA_8888: | ||||
| 		cfg |= VG_IN_CON_IMG_FORMAT_RGBA8888; | ||||
| 		break; | ||||
| 	case DECON_PIXEL_FORMAT_BGRA_8888: | ||||
| 		cfg |= VG_IN_CON_IMG_FORMAT_BGRA8888; | ||||
| 		break; | ||||
| 	case DECON_PIXEL_FORMAT_XRGB_8888: | ||||
| 		cfg |= VG_IN_CON_IMG_FORMAT_XRGB8888; | ||||
| 		break; | ||||
| 	case DECON_PIXEL_FORMAT_XBGR_8888: | ||||
| 		cfg |= VG_IN_CON_IMG_FORMAT_XBGR8888; | ||||
| 		break; | ||||
| 	case DECON_PIXEL_FORMAT_RGBX_8888: | ||||
| 		cfg |= VG_IN_CON_IMG_FORMAT_RGBX8888; | ||||
| 		break; | ||||
| 	case DECON_PIXEL_FORMAT_BGRX_8888: | ||||
| 		cfg |= VG_IN_CON_IMG_FORMAT_BGRX8888; | ||||
| 		break; | ||||
| 	case DECON_PIXEL_FORMAT_RGB_565: | ||||
| 		cfg |= VG_IN_CON_IMG_FORMAT_RGB565; | ||||
| 		break; | ||||
| 	case DECON_PIXEL_FORMAT_NV16: | ||||
| 		cfg |= VG_IN_CON_IMG_FORMAT_YUV422_2P; | ||||
| 		break; | ||||
| 	case DECON_PIXEL_FORMAT_NV61: | ||||
| 		cfg |= VG_IN_CON_IMG_FORMAT_YVU422_2P; | ||||
| 		break; | ||||
| 	case DECON_PIXEL_FORMAT_NV12: | ||||
| 	case DECON_PIXEL_FORMAT_NV12M: | ||||
| 		cfg |= VG_IN_CON_IMG_FORMAT_YUV420_2P; | ||||
| 		break; | ||||
| 	case DECON_PIXEL_FORMAT_NV21: | ||||
| 	case DECON_PIXEL_FORMAT_NV21M: | ||||
| 		cfg |= VG_IN_CON_IMG_FORMAT_YVU420_2P; | ||||
| 		break; | ||||
| 	default: | ||||
| 		vpp_err("Unsupported Format\n"); | ||||
| 		return -EINVAL; | ||||
| 	} | ||||
| 
 | ||||
| 	vpp_write(id, VG_IN_CON, cfg); | ||||
| 
 | ||||
| 	return 0; | ||||
| } | ||||
| 
 | ||||
| void vpp_reg_set_h_coef(u32 id, u32 h_ratio) | ||||
| { | ||||
| 	int i, j, k, sc_ratio; | ||||
| 
 | ||||
| 	if (h_ratio <= VPP_SC_RATIO_MAX) | ||||
| 		sc_ratio = 0; | ||||
| 	else if (h_ratio <= VPP_SC_RATIO_7_8) | ||||
| 		sc_ratio = 1; | ||||
| 	else if (h_ratio <= VPP_SC_RATIO_6_8) | ||||
| 		sc_ratio = 2; | ||||
| 	else if (h_ratio <= VPP_SC_RATIO_5_8) | ||||
| 		sc_ratio = 3; | ||||
| 	else if (h_ratio <= VPP_SC_RATIO_4_8) | ||||
| 		sc_ratio = 4; | ||||
| 	else if (h_ratio <= VPP_SC_RATIO_3_8) | ||||
| 		sc_ratio = 5; | ||||
| 	else | ||||
| 		sc_ratio = 6; | ||||
| 
 | ||||
| 	for (i = 0; i < 9; i++) { | ||||
| 		for (j = 0; j < 8; j++) { | ||||
| 			for (k = 0; k < 2; k++) { | ||||
| 				vpp_write(id, VG_H_COEF(i, j, k), | ||||
| 						h_coef_8t[sc_ratio][i][j]); | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| void vpp_reg_set_v_coef(u32 id, u32 v_ratio) | ||||
| { | ||||
| 	int i, j, k, sc_ratio; | ||||
| 
 | ||||
| 	if (v_ratio <= VPP_SC_RATIO_MAX) | ||||
| 		sc_ratio = 0; | ||||
| 	else if (v_ratio <= VPP_SC_RATIO_7_8) | ||||
| 		sc_ratio = 1; | ||||
| 	else if (v_ratio <= VPP_SC_RATIO_6_8) | ||||
| 		sc_ratio = 2; | ||||
| 	else if (v_ratio <= VPP_SC_RATIO_5_8) | ||||
| 		sc_ratio = 3; | ||||
| 	else if (v_ratio <= VPP_SC_RATIO_4_8) | ||||
| 		sc_ratio = 4; | ||||
| 	else if (v_ratio <= VPP_SC_RATIO_3_8) | ||||
| 		sc_ratio = 5; | ||||
| 	else | ||||
| 		sc_ratio = 6; | ||||
| 
 | ||||
| 	for (i = 0; i < 9; i++) { | ||||
| 		for (j = 0; j < 4; j++) { | ||||
| 			for (k = 0; k < 2; k++) { | ||||
| 				vpp_write(id, VG_V_COEF(i, j, k), | ||||
| 						v_coef_4t[sc_ratio][i][j]); | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| int vpp_reg_set_rotation(u32 id, struct vpp_size_param *p) | ||||
| { | ||||
| 	vpp_write_mask(id, VG_IN_CON, p->rot << 8, VG_IN_CON_IN_ROTATION_MASK); | ||||
| 	return 0; | ||||
| } | ||||
| 
 | ||||
| void vpp_reg_set_scale_ratio(u32 id, struct vpp_size_param *p, u32 rot_en) | ||||
| { | ||||
| 	u32 h_ratio, v_ratio = 0; | ||||
| 	u32 tmp_width, tmp_height = 0; | ||||
| 	u32 tmp_fr_w, tmp_fr_h = 0; | ||||
| 
 | ||||
| 	if (rot_en) { | ||||
| 		tmp_width = p->src_h; | ||||
| 		tmp_height = p->src_w; | ||||
| 		tmp_fr_w = p->fr_h; | ||||
| 		tmp_fr_h = p->fr_w; | ||||
| 	} else { | ||||
| 		tmp_width = p->src_w; | ||||
| 		tmp_height = p->src_h; | ||||
| 		tmp_fr_w = p->fr_w; | ||||
| 		tmp_fr_h = p->fr_h; | ||||
| 	} | ||||
| 
 | ||||
| 	h_ratio = ((tmp_width << 20) + tmp_fr_w) / p->dst_w; | ||||
| 	v_ratio = ((tmp_height << 20) + tmp_fr_h) / p->dst_h; | ||||
| 
 | ||||
| 	if (p->vpp_h_ratio != h_ratio) { | ||||
| 		vpp_write(id, VG_H_RATIO, h_ratio); | ||||
| 		vpp_reg_set_h_coef(id, h_ratio); | ||||
| 	} | ||||
| 
 | ||||
| 	if (p->vpp_v_ratio != v_ratio) { | ||||
| 		vpp_write(id, VG_V_RATIO, v_ratio); | ||||
| 		vpp_reg_set_v_coef(id, v_ratio); | ||||
| 	} | ||||
| 
 | ||||
| 	p->vpp_h_ratio = h_ratio; | ||||
| 	p->vpp_v_ratio = v_ratio; | ||||
| 
 | ||||
| 	vpp_dbg("h_ratio : %#x, v_ratio : %#x\n", p->vpp_h_ratio, p->vpp_v_ratio); | ||||
| } | ||||
| 
 | ||||
| void vpp_reg_set_in_buf_addr(u32 id, struct vpp_size_param *p) | ||||
| { | ||||
| 	vpp_dbg("y : %llu, cb : %llu, cr : %llu\n", p->addr0, p->addr1, p->addr2); | ||||
| 	vpp_write(id, VG_BASE_ADDR_Y(0), p->addr0); | ||||
| 	vpp_write(id, VG_BASE_ADDR_CB(0), p->addr1); | ||||
| 	vpp_write(id, VG_PINGPONG_UPDATE, VG_ADDR_PINGPONG_UPDATE); | ||||
| } | ||||
| 
 | ||||
| void vpp_reg_set_in_size(u32 id, struct vpp_size_param *p) | ||||
| { | ||||
| 	u32 cfg = 0; | ||||
| 
 | ||||
| 	/* source offset */ | ||||
| 	cfg = VG_SRC_OFFSET_X(p->src_x) | VG_SRC_OFFSET_Y(p->src_y); | ||||
| 	vpp_write(id, VG_SRC_OFFSET, cfg); | ||||
| 
 | ||||
| 	/* source full(alloc) size */ | ||||
| 	cfg = VG_SRC_SIZE_WIDTH(p->src_fw) | VG_SRC_SIZE_HEIGHT(p->src_fh); | ||||
| 	vpp_write(id, VG_SRC_SIZE, cfg); | ||||
| 
 | ||||
| 	/* source cropped size */ | ||||
| 	cfg = VG_IMG_SIZE_WIDTH(p->src_w) | VG_IMG_SIZE_HEIGHT(p->src_h); | ||||
| 	vpp_write(id, VG_IMG_SIZE, cfg); | ||||
| 
 | ||||
| 	if (p->fr_w) | ||||
| 		p->src_w--; | ||||
| 	if (p->fr_h) | ||||
| 		p->src_h--; | ||||
| 
 | ||||
| 	/* fraction position */ | ||||
| 	vpp_write(id, VG_YHPOSITION0, p->fr_yx); | ||||
| 	vpp_write(id, VG_YVPOSITION0, p->fr_yy); | ||||
| 	vpp_write(id, VG_CHPOSITION0, p->fr_cx); | ||||
| 	vpp_write(id, VG_CVPOSITION0, p->fr_cy); | ||||
| } | ||||
| 
 | ||||
| void vpp_reg_set_in_block_size(u32 id, u32 enable, struct vpp_size_param *p) | ||||
| { | ||||
| 	u32 cfg = 0; | ||||
| 
 | ||||
| 	if (!enable) { | ||||
| 		vpp_write_mask(id, VG_IN_CON, 0, VG_IN_CON_BLOCKING_FEATURE_EN); | ||||
| 		return; | ||||
| 	} | ||||
| 
 | ||||
| 	/* blocking area offset */ | ||||
| 	cfg = VG_BLK_OFFSET_X(p->block_x) | VG_BLK_OFFSET_Y(p->block_y); | ||||
| 	vpp_write(id, VG_BLK_OFFSET, cfg); | ||||
| 
 | ||||
| 	/* blocking area size */ | ||||
| 	cfg = VG_BLK_SIZE_WIDTH(p->block_w) | VG_BLK_SIZE_HEIGHT(p->block_h); | ||||
| 	vpp_write(id, VG_BLK_SIZE, cfg); | ||||
| 
 | ||||
| 	vpp_write_mask(id, VG_IN_CON, ~0, VG_IN_CON_BLOCKING_FEATURE_EN); | ||||
| 
 | ||||
| 	vpp_dbg("block x : %d, y : %d, w : %d, h : %d\n", | ||||
| 			p->block_x, p->block_y, p->block_w, p->block_h); | ||||
| } | ||||
| 
 | ||||
| void vpp_reg_set_out_size(u32 id, u32 dst_w, u32 dst_h) | ||||
| { | ||||
| 	u32 cfg = 0; | ||||
| 
 | ||||
| 	/* destination scaled size */ | ||||
| 	cfg = VG_SCALED_SIZE_WIDTH(dst_w) | VG_SCALED_SIZE_HEIGHT(dst_h); | ||||
| 	vpp_write(id, VG_SCALED_SIZE, cfg); | ||||
| } | ||||
| 
 | ||||
| void vpp_reg_set_rgb_type(u32 id, u32 type) | ||||
| { | ||||
| 	u32 csc_eq = 0; | ||||
| 
 | ||||
| 	switch (type) { | ||||
| 	case BT_601_NARROW: | ||||
| 		csc_eq = VG_OUT_CON_RGB_TYPE_601_NARROW; | ||||
| 		break; | ||||
| 	case BT_601_WIDE: | ||||
| 		csc_eq = VG_OUT_CON_RGB_TYPE_601_WIDE; | ||||
| 		break; | ||||
| 	case BT_709_NARROW: | ||||
| 		csc_eq = VG_OUT_CON_RGB_TYPE_709_NARROW; | ||||
| 		break; | ||||
| 	case BT_709_WIDE: | ||||
| 		csc_eq = VG_OUT_CON_RGB_TYPE_709_WIDE; | ||||
| 		break; | ||||
| 	default: | ||||
| 		vpp_err("Unsupported CSC Equation\n"); | ||||
| 	} | ||||
| 
 | ||||
| 	vpp_write(id, VG_OUT_CON, csc_eq); | ||||
| } | ||||
| 
 | ||||
| void vpp_reg_set_plane_alpha(u32 id, u32 plane_alpha) | ||||
| { | ||||
| 	if (plane_alpha > 0xFF) | ||||
| 		vpp_info("%d is too much value\n", plane_alpha); | ||||
| 	vpp_write_mask(id, VG_OUT_CON, VG_OUT_CON_FRAME_ALPHA(plane_alpha), | ||||
| 			VG_OUT_CON_FRAME_ALPHA_MASK); | ||||
| } | ||||
| 
 | ||||
| void vpp_reg_set_plane_alpha_fixed(u32 id) | ||||
| { | ||||
| 	vpp_write_mask(id, VG_OUT_CON, VG_OUT_CON_FRAME_ALPHA(0xFF), | ||||
| 			VG_OUT_CON_FRAME_ALPHA_MASK); | ||||
| } | ||||
| 
 | ||||
| void vpp_reg_set_smart_if_pix_num(u32 id, u32 dst_w, u32 dst_h) | ||||
| { | ||||
| 	vpp_write(id, VG_SMART_IF_PIXEL_NUM, dst_w * dst_h); | ||||
| } | ||||
| 
 | ||||
| void vpp_reg_set_lookup_table(u32 id) | ||||
| { | ||||
| 	vpp_write(id, VG_QOS_LUT07_00, 0x44444444); | ||||
| 	vpp_write(id, VG_QOS_LUT15_08, 0x44444444); | ||||
| } | ||||
| 
 | ||||
| void vpp_reg_set_dynamic_clock_gating(u32 id) | ||||
| { | ||||
| 	vpp_write(id, VG_DYNAMIC_GATING_ENABLE, 0x3F); | ||||
| } | ||||
| 
 | ||||
| int vpp_reg_get_irq_status(u32 id) | ||||
| { | ||||
| 	u32 cfg = vpp_read(id, VG_IRQ); | ||||
| 	cfg &= (VG_IRQ_SFR_UPDATE_DONE | VG_IRQ_HW_RESET_DONE | | ||||
| 		VG_IRQ_READ_SLAVE_ERROR | VG_IRQ_DEADLOCK_STATUS | | ||||
| 		VG_IRQ_FRAMEDONE); | ||||
| 	return cfg; | ||||
| } | ||||
| 
 | ||||
| void vpp_reg_set_clear_irq(u32 id, u32 irq) | ||||
| { | ||||
| 	vpp_write_mask(id, VG_IRQ, ~0, irq); | ||||
| } | ||||
| 
 | ||||
| void vpp_constraints_params(struct vpp_size_constraints *vc, struct vpp_img_format *vi) | ||||
| { | ||||
| 	if (!vi->wb) { | ||||
| 		if (!vi->vgr) { | ||||
| 			if (vi->yuv) { | ||||
| 				vc->src_mul_w = YUV_SRC_SIZE_MULTIPLE; | ||||
| 				vc->src_mul_h = YUV_SRC_SIZE_MULTIPLE; | ||||
| 				vc->src_w_min = YUV_SRC_WIDTH_MIN; | ||||
| 				vc->src_w_max = YUV_SRC_WIDTH_MAX; | ||||
| 				vc->src_h_min = YUV_SRC_HEIGHT_MIN; | ||||
| 				vc->src_h_max = YUV_SRC_HEIGHT_MAX; | ||||
| 				vc->img_mul_w = YUV_IMG_SIZE_MULTIPLE; | ||||
| 				vc->img_mul_h = YUV_IMG_SIZE_MULTIPLE; | ||||
| 				vc->img_w_min = YUV_IMG_WIDTH_MIN; | ||||
| 				vc->img_w_max = IMG_WIDTH_MAX; | ||||
| 				vc->img_h_min = YUV_IMG_HEIGHT_MIN; | ||||
| 				vc->img_h_max = IMG_WIDTH_MAX; | ||||
| 				vc->src_mul_x = YUV_SRC_OFFSET_MULTIPLE; | ||||
| 				vc->src_mul_y = YUV_SRC_OFFSET_MULTIPLE; | ||||
| 				vc->sca_w_min = SCALED_WIDTH_MIN; | ||||
| 				vc->sca_w_max = SCALED_WIDTH_MAX; | ||||
| 				vc->sca_h_min = SCALED_HEIGHT_MIN; | ||||
| 				vc->sca_h_max = SCALED_HEIGHT_MAX; | ||||
| 				vc->sca_mul_w = SCALED_SIZE_MULTIPLE; | ||||
| 				vc->sca_mul_h = SCALED_SIZE_MULTIPLE; | ||||
| 			} else { | ||||
| 				vc->src_mul_w = RGB_SRC_SIZE_MULTIPLE; | ||||
| 				vc->src_mul_h = RGB_SRC_SIZE_MULTIPLE; | ||||
| 				vc->src_w_min = RGB_SRC_WIDTH_MIN; | ||||
| 				vc->src_w_max = RGB_SRC_WIDTH_MAX; | ||||
| 				vc->src_h_min = RGB_SRC_HEIGHT_MIN; | ||||
| 				vc->src_h_max = RGB_SRC_HEIGHT_MAX; | ||||
| 				vc->img_mul_w = RGB_IMG_SIZE_MULTIPLE; | ||||
| 				vc->img_mul_h = RGB_IMG_SIZE_MULTIPLE; | ||||
| 				vc->img_w_min = RGB_IMG_WIDTH_MIN; | ||||
| 				vc->img_w_max = IMG_WIDTH_MAX; | ||||
| 				vc->img_h_min = RGB_IMG_HEIGHT_MIN; | ||||
| 				vc->img_h_max = IMG_WIDTH_MAX; | ||||
| 				vc->src_mul_x = RGB_SRC_OFFSET_MULTIPLE; | ||||
| 				vc->src_mul_y = RGB_SRC_OFFSET_MULTIPLE; | ||||
| 				vc->sca_w_min = SCALED_WIDTH_MIN; | ||||
| 				vc->sca_w_max = SCALED_WIDTH_MAX; | ||||
| 				vc->sca_h_min = SCALED_HEIGHT_MIN; | ||||
| 				vc->sca_h_max = SCALED_HEIGHT_MAX; | ||||
| 				vc->sca_mul_w = SCALED_SIZE_MULTIPLE; | ||||
| 				vc->sca_mul_h = SCALED_SIZE_MULTIPLE; | ||||
| 			} | ||||
| 		} else { | ||||
| 			if (!vi->yuv) { | ||||
| 				vc->src_mul_w = RGB_SRC_SIZE_MULTIPLE; | ||||
| 				vc->src_mul_h = RGB_SRC_SIZE_MULTIPLE; | ||||
| 				vc->src_w_max = RGB_SRC_WIDTH_MAX; | ||||
| 				vc->src_h_max = RGB_SRC_HEIGHT_MAX; | ||||
| 				vc->sca_w_min = SCALED_WIDTH_MIN; | ||||
| 				vc->sca_w_max = SCALED_WIDTH_MAX; | ||||
| 				vc->sca_h_min = SCALED_HEIGHT_MIN; | ||||
| 				vc->sca_h_max = SCALED_HEIGHT_MAX; | ||||
| 				vc->src_mul_x = RGB_SRC_OFFSET_MULTIPLE; | ||||
| 				vc->src_mul_y = RGB_SRC_OFFSET_MULTIPLE; | ||||
| 				vc->sca_mul_w = SCALED_SIZE_MULTIPLE; | ||||
| 
 | ||||
| 				if (vi->pre_none) { | ||||
| 					vc->img_mul_w = PRE_RGB_WIDTH; | ||||
| 					vc->img_mul_h = PRE_RGB_HEIGHT; | ||||
| 				} else if (vi->pre_12) { | ||||
| 					vc->img_mul_w = PRE12_RGB_WIDTH; | ||||
| 					vc->img_mul_h = PRE12_RGB_HEIGHT; | ||||
| 				} else if (vi->pre_14) { | ||||
| 					vc->img_mul_w = PRE14_RGB_WIDTH; | ||||
| 					vc->img_mul_h = PRE14_RGB_HEIGHT; | ||||
| 				} | ||||
| 				if (!vi->rot) { | ||||
| 					vc->src_w_min = ROT1_RGB_SRC_WIDTH_MIN; | ||||
| 					vc->src_h_min = ROT1_RGB_SRC_HEIGHT_MIN; | ||||
| 					vc->img_w_min = ROT1_RGB_IMG_WIDTH_MIN; | ||||
| 					vc->img_h_min = ROT1_RGB_IMG_HEIGHT_MIN; | ||||
| 					vc->sca_mul_h = SCALED_SIZE_MULTIPLE; | ||||
| 				} else { | ||||
| 					vc->src_w_min = ROT2_RGB_SRC_WIDTH_MIN; | ||||
| 					vc->src_h_min = ROT2_RGB_SRC_HEIGHT_MIN; | ||||
| 					vc->img_w_min = ROT2_RGB_IMG_WIDTH_MIN; | ||||
| 					vc->img_h_min = ROT2_RGB_IMG_HEIGHT_MIN; | ||||
| 					vc->sca_mul_h = SCALED_SIZE_MULTIPLE; | ||||
| 				} | ||||
| 				if (vi->normal) { | ||||
| 					vc->img_w_max = ROT3_RGB_IMG_WIDTH_MAX; | ||||
| 					vc->img_h_max = ROT3_RGB_IMG_HEIGHT_MAX; | ||||
| 				} else { | ||||
| 					vc->img_w_max = ROT4_RGB_IMG_WIDTH_MAX; | ||||
| 					vc->img_h_max = ROT4_RGB_IMG_HEIGHT_MAX; | ||||
| 					vc->blk_w_min = ROT3_RGB_BLK_WIDTH_MIN; | ||||
| 					vc->blk_w_max = ROT3_RGB_BLK_WIDTH_MAX; | ||||
| 					vc->blk_h_min = ROT3_RGB_BLK_HEIGHT_MIN; | ||||
| 					vc->blk_h_max = ROT3_RGB_BLK_HEIGHT_MAX; | ||||
| 				} | ||||
| 			} else { | ||||
| 				vc->src_mul_w = YUV_SRC_SIZE_MULTIPLE; | ||||
| 				vc->src_w_max = YUV_SRC_WIDTH_MAX; | ||||
| 				vc->src_h_max = YUV_SRC_HEIGHT_MAX; | ||||
| 				vc->sca_w_min = SCALED_WIDTH_MIN; | ||||
| 				vc->sca_w_max = SCALED_WIDTH_MAX; | ||||
| 				vc->sca_h_min = SCALED_HEIGHT_MIN; | ||||
| 				vc->sca_h_max = SCALED_HEIGHT_MAX; | ||||
| 				vc->src_mul_x = SRC_SIZE_MULTIPLE; | ||||
| 				vc->sca_mul_w = SCALED_SIZE_MULTIPLE; | ||||
| 
 | ||||
| 				if (!vi->rot) { | ||||
| 					vc->src_w_min = ROT1_YUV_SRC_WIDTH_MIN; | ||||
| 					vc->src_h_min = ROT1_YUV_SRC_HEIGHT_MIN; | ||||
| 					vc->img_w_min = ROT1_YUV_IMG_WIDTH_MIN; | ||||
| 					vc->img_h_min = ROT1_YUV_IMG_HEIGHT_MIN; | ||||
| 				} else { | ||||
| 					vc->src_w_min = ROT2_YUV_SRC_WIDTH_MIN; | ||||
| 					vc->src_h_min = ROT2_YUV_SRC_HEIGHT_MIN; | ||||
| 					vc->img_w_min = ROT2_YUV_IMG_WIDTH_MIN; | ||||
| 					vc->img_h_min = ROT2_YUV_IMG_HEIGHT_MIN; | ||||
| 				} | ||||
| 				if (vi->normal) { | ||||
| 					vc->img_w_max = ROT3_YUV_IMG_WIDTH_MAX; | ||||
| 					vc->img_h_max = ROT3_YUV_IMG_HEIGHT_MAX; | ||||
| 				} else { | ||||
| 					vc->img_w_max = ROT4_YUV_IMG_WIDTH_MAX; | ||||
| 					vc->img_h_max = ROT4_YUV_IMG_HEIGHT_MAX; | ||||
| 				} | ||||
| 				if (vi->yuv422) { | ||||
| 					vc->src_mul_h = YUV_SRC_SIZE_MUL_HEIGHT; | ||||
| 					if (vi->pre_none) { | ||||
| 						vc->img_mul_w = PRE_YUV_WIDTH; | ||||
| 						if (!vi->rot) | ||||
| 							vc->img_mul_h = PRE_ROT1_YUV_HEIGHT; | ||||
| 						else | ||||
| 							vc->img_mul_h = PRE_YUV_HEIGHT; | ||||
| 
 | ||||
| 					} else if (vi->pre_12) { | ||||
| 						vc->img_mul_w = PRE12_YUV_WIDTH; | ||||
| 						if (!vi->rot) | ||||
| 							vc->img_mul_h = PRE12_ROT1_YUV_HEIGHT; | ||||
| 						else | ||||
| 							vc->img_mul_h = PRE12_YUV_HEIGHT; | ||||
| 					} else if (vi->pre_14) { | ||||
| 						vc->img_mul_w = PRE14_YUV_WIDTH; | ||||
| 						if (!vi->rot) { | ||||
| 							vc->img_mul_h = PRE14_ROT1_YUV_HEIGHT; | ||||
| 						} else { | ||||
| 							vc->img_mul_h = PRE14_YUV_HEIGHT; | ||||
| 						} | ||||
| 					} | ||||
| 					if (!vi->rot) { | ||||
| 						vc->src_mul_y = SRC_ROT2_MUL_Y; | ||||
| 						vc->sca_mul_h = SCALED_SIZE_MULTIPLE; | ||||
| 					} else { | ||||
| 						vc->src_mul_y = SRC_ROT1_MUL_Y; | ||||
| 						vc->sca_mul_h = SCALED_SIZE_MULTIPLE; | ||||
| 					} | ||||
| 				} else { | ||||
| 					vc->src_mul_h = YUV_SRC_SIZE_MULTIPLE; | ||||
| 					vc->src_mul_y = YUV_SRC_OFFSET_MULTIPLE; | ||||
| 					vc->sca_mul_h = SCALED_SIZE_MULTIPLE; | ||||
| 					if (vi->pre_none) { | ||||
| 						vc->img_mul_w = PRE_YUV_WIDTH; | ||||
| 						vc->img_mul_h = PRE_YUV_HEIGHT; | ||||
| 					} else if (vi->pre_12) { | ||||
| 						vc->img_mul_w = PRE12_YUV_WIDTH; | ||||
| 						vc->img_mul_h = PRE12_YUV_HEIGHT; | ||||
| 					} else if (vi->pre_14) { | ||||
| 						vc->img_mul_w = PRE14_YUV_WIDTH; | ||||
| 						vc->img_mul_h = PRE14_YUV_HEIGHT; | ||||
| 					} | ||||
| 				} | ||||
| 			} | ||||
| 		} | ||||
| 	} else { /* write-back case */ | ||||
| 		vc->src_mul_w = DST_SIZE_MULTIPLE; | ||||
| 		vc->src_mul_h = DST_SIZE_MULTIPLE; | ||||
| 		vc->src_w_min = DST_SIZE_WIDTH_MIN; | ||||
| 		vc->src_w_max = DST_SIZE_WIDTH_MAX; | ||||
| 		vc->src_h_min = DST_SIZE_HEIGHT_MIN; | ||||
| 		vc->src_h_max = DST_SIZE_HEIGHT_MAX; | ||||
| 		vc->img_mul_w = DST_IMGAGE_MULTIPLE; | ||||
| 		vc->img_mul_h = DST_IMGAGE_MULTIPLE; | ||||
| 		vc->img_w_min = DST_IMG_WIDTH_MIN; | ||||
| 		vc->img_w_max = DST_IMG_MAX; | ||||
| 		vc->img_h_min = DST_IMG_HEIGHT_MIN; | ||||
| 		vc->img_h_max = DST_IMG_MAX; | ||||
| 		vc->sca_w_min = DST_SIZE_WIDTH_MIN; | ||||
| 		vc->sca_w_max = DST_SIZE_WIDTH_MAX; | ||||
| 		vc->sca_h_min = DST_SIZE_HEIGHT_MIN; | ||||
| 		vc->sca_h_max = DST_SIZE_HEIGHT_MAX; | ||||
| 		vc->src_mul_x = DST_OFFSET_MULTIPLE; | ||||
| 		vc->src_mul_y = DST_OFFSET_MULTIPLE; | ||||
| 		vc->sca_mul_w = DST_OFFSET_MULTIPLE; | ||||
| 		vc->sca_mul_h = DST_OFFSET_MULTIPLE; | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| void vpp_reg_init(u32 id) | ||||
| { | ||||
| 	vpp_reg_set_realtime_path(id); | ||||
| 	vpp_reg_set_framedone_irq(id, false); | ||||
| 	vpp_reg_set_deadlock_irq(id, false); | ||||
| 	vpp_reg_set_read_slave_err_irq(id, false); | ||||
| 	vpp_reg_set_hw_reset_done_mask(id, false); | ||||
| 	vpp_reg_set_sfr_update_done_irq(id, false); | ||||
| 	vpp_reg_set_enable_interrupt(id); | ||||
| 	vpp_reg_set_lookup_table(id); | ||||
| 	vpp_reg_set_dynamic_clock_gating(id); | ||||
| 	vpp_reg_set_plane_alpha_fixed(id); | ||||
| } | ||||
| 
 | ||||
| void vpp_reg_deinit(u32 id, u32 reset_en) | ||||
| { | ||||
| 	unsigned int vpp_irq = 0; | ||||
| 
 | ||||
| 	vpp_irq = vpp_reg_get_irq_status(id); | ||||
| 	vpp_reg_set_clear_irq(id, vpp_irq); | ||||
| 
 | ||||
| 	vpp_reg_set_framedone_irq(id, true); | ||||
| 	vpp_reg_set_deadlock_irq(id, true); | ||||
| 	vpp_reg_set_read_slave_err_irq(id, true); | ||||
| 	vpp_reg_set_hw_reset_done_mask(id, true); | ||||
| 	vpp_reg_set_sfr_update_done_irq(id, true); | ||||
| 	if (reset_en) | ||||
| 		vpp_reg_set_sw_reset(id); | ||||
| } | ||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 awab228
						awab228