1/*
2 * Frame buffer driver for ADV7393/2 video encoder
3 *
4 * Copyright 2006-2009 Analog Devices Inc.
5 * Licensed under the GPL-2 or late.
6 */
7
8#ifndef __BFIN_ADV7393FB_H__
9#define __BFIN_ADV7393FB_H__
10
11#define BFIN_LCD_NBR_PALETTE_ENTRIES	256
12
13#ifdef CONFIG_NTSC
14# define VMODE 0
15#endif
16#ifdef CONFIG_PAL
17# define VMODE 1
18#endif
19#ifdef CONFIG_NTSC_640x480
20# define VMODE 2
21#endif
22#ifdef CONFIG_PAL_640x480
23# define VMODE 3
24#endif
25#ifdef CONFIG_NTSC_YCBCR
26# define VMODE 4
27#endif
28#ifdef CONFIG_PAL_YCBCR
29# define VMODE 5
30#endif
31
32#ifndef VMODE
33# define VMODE 1
34#endif
35
36#ifdef CONFIG_ADV7393_2XMEM
37# define VMEM 2
38#else
39# define VMEM 1
40#endif
41
42#if defined(CONFIG_BF537) || defined(CONFIG_BF536) || defined(CONFIG_BF534)
43# define DMA_CFG_VAL	0x7935	/* Set Sync Bit */
44# define VB_DUMMY_MEMORY_SOURCE	L1_DATA_B_START
45#else
46# define DMA_CFG_VAL	0x7915
47# define VB_DUMMY_MEMORY_SOURCE	BOOT_ROM_START
48#endif
49
50enum {
51	DESTRUCT,
52	BUILD,
53};
54
55enum {
56	POWER_ON,
57	POWER_DOWN,
58	BLANK_ON,
59	BLANK_OFF,
60};
61
62#define DRIVER_NAME "bfin-adv7393"
63
64struct adv7393fb_modes {
65	const s8 name[25];	/* Full name */
66	u16 xres;		/* Active Horizonzal Pixels  */
67	u16 yres;		/* Active Vertical Pixels  */
68	u16 bpp;
69	u16 vmode;
70	u16 a_lines;		/* Active Lines per Field */
71	u16 vb1_lines;		/* Vertical Blanking Field 1 Lines */
72	u16 vb2_lines;		/* Vertical Blanking Field 2 Lines */
73	u16 tot_lines;		/* Total Lines per Frame */
74	u16 boeft_blank;	/* Before Odd/Even Field Transition No. of Blank Pixels */
75	u16 aoeft_blank;	/* After Odd/Even Field Transition No. of Blank Pixels */
76	const s8 *adv7393_i2c_initd;
77	u16 adv7393_i2c_initd_len;
78};
79
80static const u8 init_NTSC_TESTPATTERN[] = {
81	0x00, 0x1E,	/* Power up all DACs and PLL */
82	0x01, 0x00,	/* SD-Only Mode */
83	0x80, 0x10,	/* SSAF Luma Filter Enabled, NTSC Mode */
84	0x82, 0xCB,	/* Step control on, pixel data valid, pedestal on, PrPb SSAF on, CVBS/YC output */
85	0x84, 0x40,	/* SD Color Bar Test Pattern Enabled, DAC 2 = Luma, DAC 3 = Chroma */
86};
87
88static const u8 init_NTSC[] = {
89	0x00, 0x1E,	/* Power up all DACs and PLL */
90	0xC3, 0x26,	/* Program RGB->YCrCb Color Space conversion matrix */
91	0xC5, 0x12,	/* Program RGB->YCrCb Color Space conversion matrix */
92	0xC2, 0x4A,	/* Program RGB->YCrCb Color Space conversion matrix */
93	0xC6, 0x5E,	/* Program RGB->YCrCb Color Space conversion matrix */
94	0xBD, 0x19,	/* Program RGB->YCrCb Color Space conversion matrix */
95	0xBF, 0x42,	/* Program RGB->YCrCb Color Space conversion matrix */
96	0x8C, 0x1F,	/* NTSC Subcarrier Frequency */
97	0x8D, 0x7C,	/* NTSC Subcarrier Frequency */
98	0x8E, 0xF0,	/* NTSC Subcarrier Frequency */
99	0x8F, 0x21,	/* NTSC Subcarrier Frequency */
100	0x01, 0x00,	/* SD-Only Mode */
101	0x80, 0x30,	/* SSAF Luma Filter Enabled, NTSC Mode */
102	0x82, 0x8B,	/* Step control on, pixel data invalid, pedestal on, PrPb SSAF on, CVBS/YC output */
103	0x87, 0x80,	/* SD Color Bar Test Pattern Enabled, DAC 2 = Luma, DAC 3 = Chroma */
104	0x86, 0x82,
105	0x8B, 0x11,
106	0x88, 0x20,
107	0x8A, 0x0d,
108};
109
110static const u8 init_PAL[] = {
111	0x00, 0x1E,	/* Power up all DACs and PLL */
112	0xC3, 0x26,	/* Program RGB->YCrCb Color Space conversion matrix */
113	0xC5, 0x12,	/* Program RGB->YCrCb Color Space conversion matrix */
114	0xC2, 0x4A,	/* Program RGB->YCrCb Color Space conversion matrix */
115	0xC6, 0x5E,	/* Program RGB->YCrCb Color Space conversion matrix */
116	0xBD, 0x19,	/* Program RGB->YCrCb Color Space conversion matrix */
117	0xBF, 0x42,	/* Program RGB->YCrCb Color Space conversion matrix */
118	0x8C, 0xCB,	/* PAL Subcarrier Frequency */
119	0x8D, 0x8A,	/* PAL Subcarrier Frequency */
120	0x8E, 0x09,	/* PAL Subcarrier Frequency */
121	0x8F, 0x2A,	/* PAL Subcarrier Frequency */
122	0x01, 0x00,	/* SD-Only Mode */
123	0x80, 0x11,	/* SSAF Luma Filter Enabled, PAL Mode */
124	0x82, 0x8B,	/* Step control on, pixel data invalid, pedestal on, PrPb SSAF on, CVBS/YC output */
125	0x87, 0x80,	/* SD Color Bar Test Pattern Enabled, DAC 2 = Luma, DAC 3 = Chroma */
126	0x86, 0x82,
127	0x8B, 0x11,
128	0x88, 0x20,
129	0x8A, 0x0d,
130};
131
132static const u8 init_NTSC_YCbCr[] = {
133	0x00, 0x1E,	/* Power up all DACs and PLL */
134	0x8C, 0x1F,	/* NTSC Subcarrier Frequency */
135	0x8D, 0x7C,	/* NTSC Subcarrier Frequency */
136	0x8E, 0xF0,	/* NTSC Subcarrier Frequency */
137	0x8F, 0x21,	/* NTSC Subcarrier Frequency */
138	0x01, 0x00,	/* SD-Only Mode */
139	0x80, 0x30,	/* SSAF Luma Filter Enabled, NTSC Mode */
140	0x82, 0x8B,	/* Step control on, pixel data invalid, pedestal on, PrPb SSAF on, CVBS/YC output */
141	0x87, 0x00,	/* DAC 2 = Luma, DAC 3 = Chroma */
142	0x86, 0x82,
143	0x8B, 0x11,
144	0x88, 0x08,
145	0x8A, 0x0d,
146};
147
148static const u8 init_PAL_YCbCr[] = {
149	0x00, 0x1E,	/* Power up all DACs and PLL */
150	0x8C, 0xCB,	/* PAL Subcarrier Frequency */
151	0x8D, 0x8A,	/* PAL Subcarrier Frequency */
152	0x8E, 0x09,	/* PAL Subcarrier Frequency */
153	0x8F, 0x2A,	/* PAL Subcarrier Frequency */
154	0x01, 0x00,	/* SD-Only Mode */
155	0x80, 0x11,	/* SSAF Luma Filter Enabled, PAL Mode */
156	0x82, 0x8B,	/* Step control on, pixel data invalid, pedestal on, PrPb SSAF on, CVBS/YC output */
157	0x87, 0x00,	/* DAC 2 = Luma, DAC 3 = Chroma */
158	0x86, 0x82,
159	0x8B, 0x11,
160	0x88, 0x08,
161	0x8A, 0x0d,
162};
163
164static struct adv7393fb_modes known_modes[] = {
165	/* NTSC 720x480 CRT */
166	{
167		.name = "NTSC 720x480",
168		.xres = 720,
169		.yres = 480,
170		.bpp = 16,
171		.vmode = FB_VMODE_INTERLACED,
172		.a_lines = 240,
173		.vb1_lines = 22,
174		.vb2_lines = 23,
175		.tot_lines = 525,
176		.boeft_blank = 16,
177		.aoeft_blank = 122,
178		.adv7393_i2c_initd = init_NTSC,
179		.adv7393_i2c_initd_len = sizeof(init_NTSC)
180	},
181	/* PAL 720x480 CRT */
182	{
183		.name = "PAL 720x576",
184		.xres = 720,
185		.yres = 576,
186		.bpp = 16,
187		.vmode = FB_VMODE_INTERLACED,
188		.a_lines = 288,
189		.vb1_lines = 24,
190		.vb2_lines = 25,
191		.tot_lines = 625,
192		.boeft_blank = 12,
193		.aoeft_blank = 132,
194		.adv7393_i2c_initd = init_PAL,
195		.adv7393_i2c_initd_len = sizeof(init_PAL)
196	},
197	/* NTSC 640x480 CRT Experimental */
198	{
199		.name = "NTSC 640x480",
200		.xres = 640,
201		.yres = 480,
202		.bpp = 16,
203		.vmode = FB_VMODE_INTERLACED,
204		.a_lines = 240,
205		.vb1_lines = 22,
206		.vb2_lines = 23,
207		.tot_lines = 525,
208		.boeft_blank = 16 + 40,
209		.aoeft_blank = 122 + 40,
210		.adv7393_i2c_initd = init_NTSC,
211		.adv7393_i2c_initd_len = sizeof(init_NTSC)
212	},
213	/* PAL 640x480 CRT Experimental */
214	{
215		.name = "PAL 640x480",
216		.xres = 640,
217		.yres = 480,
218		.bpp = 16,
219		.vmode = FB_VMODE_INTERLACED,
220		.a_lines = 288 - 20,
221		.vb1_lines = 24 + 20,
222		.vb2_lines = 25 + 20,
223		.tot_lines = 625,
224		.boeft_blank = 12 + 40,
225		.aoeft_blank = 132 + 40,
226		.adv7393_i2c_initd = init_PAL,
227		.adv7393_i2c_initd_len = sizeof(init_PAL)
228	},
229	/* NTSC 720x480 YCbCR */
230	{
231		.name = "NTSC 720x480 YCbCR",
232		.xres = 720,
233		.yres = 480,
234		.bpp = 16,
235		.vmode = FB_VMODE_INTERLACED,
236		.a_lines = 240,
237		.vb1_lines = 22,
238		.vb2_lines = 23,
239		.tot_lines = 525,
240		.boeft_blank = 16,
241		.aoeft_blank = 122,
242		.adv7393_i2c_initd = init_NTSC_YCbCr,
243		.adv7393_i2c_initd_len = sizeof(init_NTSC_YCbCr)
244	},
245	/* PAL 720x480 CRT */
246	{
247		.name = "PAL 720x576 YCbCR",
248		.xres = 720,
249		.yres = 576,
250		.bpp = 16,
251		.vmode = FB_VMODE_INTERLACED,
252		.a_lines = 288,
253		.vb1_lines = 24,
254		.vb2_lines = 25,
255		.tot_lines = 625,
256		.boeft_blank = 12,
257		.aoeft_blank = 132,
258		.adv7393_i2c_initd = init_PAL_YCbCr,
259		.adv7393_i2c_initd_len = sizeof(init_PAL_YCbCr)
260	}
261};
262
263struct adv7393fb_regs {
264
265};
266
267struct adv7393fb_device {
268	struct fb_info info;	/* FB driver info record */
269
270	struct i2c_client *client;
271
272	struct dmasg *descriptor_list_head;
273	struct dmasg *vb1;
274	struct dmasg *av1;
275	struct dmasg *vb2;
276	struct dmasg *av2;
277
278	dma_addr_t dma_handle;
279
280	struct fb_info bfin_adv7393_fb;
281
282	struct adv7393fb_modes *modes;
283
284	struct adv7393fb_regs *regs;	/* Registers memory map */
285	size_t regs_len;
286	size_t fb_len;
287	size_t line_len;
288	u16 open;
289	u16 *fb_mem;		/* RGB Buffer */
290
291};
292
293#define to_adv7393fb_device(_info) \
294	  (_info ? container_of(_info, struct adv7393fb_device, info) : NULL);
295
296static int bfin_adv7393_fb_open(struct fb_info *info, int user);
297static int bfin_adv7393_fb_release(struct fb_info *info, int user);
298static int bfin_adv7393_fb_check_var(struct fb_var_screeninfo *var,
299				     struct fb_info *info);
300
301static int bfin_adv7393_fb_pan_display(struct fb_var_screeninfo *var,
302				       struct fb_info *info);
303
304static int bfin_adv7393_fb_blank(int blank, struct fb_info *info);
305
306static void bfin_config_ppi(struct adv7393fb_device *fbdev);
307static int bfin_config_dma(struct adv7393fb_device *fbdev);
308static void bfin_disable_dma(void);
309static void bfin_enable_ppi(void);
310static void bfin_disable_ppi(void);
311
312static inline int adv7393_write(struct i2c_client *client, u8 reg, u8 value);
313static inline int adv7393_read(struct i2c_client *client, u8 reg);
314static int adv7393_write_block(struct i2c_client *client, const u8 *data,
315			       unsigned int len);
316
317int bfin_adv7393_fb_cursor(struct fb_info *info, struct fb_cursor *cursor);
318static int bfin_adv7393_fb_setcolreg(u_int, u_int, u_int, u_int,
319				     u_int, struct fb_info *info);
320
321#endif
322