• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * vpif - DM646x Video Port Interface driver
3  * VPIF is a receiver and transmitter for video data. It has two channels(0, 1)
4  * that receiveing video byte stream and two channels(2, 3) for video output.
5  * The hardware supports SDTV, HDTV formats, raw data capture.
6  * Currently, the driver supports NTSC and PAL standards.
7  *
8  * Copyright (C) 2009 Texas Instruments Incorporated - http://www.ti.com/
9  *
10  * This program is free software; you can redistribute it and/or
11  * modify it under the terms of the GNU General Public License as
12  * published by the Free Software Foundation version 2.
13  *
14  * This program is distributed .as is. WITHOUT ANY WARRANTY of any
15  * kind, whether express or implied; without even the implied warranty
16  * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17  * GNU General Public License for more details.
18  */
19 
20 #include <linux/init.h>
21 #include <linux/module.h>
22 #include <linux/platform_device.h>
23 #include <linux/spinlock.h>
24 #include <linux/kernel.h>
25 #include <linux/io.h>
26 #include <mach/hardware.h>
27 
28 #include "vpif.h"
29 
30 MODULE_DESCRIPTION("TI DaVinci Video Port Interface driver");
31 MODULE_LICENSE("GPL");
32 
33 #define VPIF_CH0_MAX_MODES	(22)
34 #define VPIF_CH1_MAX_MODES	(02)
35 #define VPIF_CH2_MAX_MODES	(15)
36 #define VPIF_CH3_MAX_MODES	(02)
37 
38 static resource_size_t	res_len;
39 static struct resource	*res;
40 spinlock_t vpif_lock;
41 
42 void __iomem *vpif_base;
43 
44 /**
45  * ch_params: video standard configuration parameters for vpif
46  * The table must include all presets from supported subdevices.
47  */
48 const struct vpif_channel_config_params ch_params[] = {
49 	/* HDTV formats */
50 	{
51 		.name = "480p59_94",
52 		.width = 720,
53 		.height = 480,
54 		.frm_fmt = 1,
55 		.ycmux_mode = 0,
56 		.eav2sav = 138-8,
57 		.sav2eav = 720,
58 		.l1 = 1,
59 		.l3 = 43,
60 		.l5 = 523,
61 		.vsize = 525,
62 		.capture_format = 0,
63 		.vbi_supported = 0,
64 		.hd_sd = 1,
65 		.dv_preset = V4L2_DV_480P59_94,
66 	},
67 	{
68 		.name = "576p50",
69 		.width = 720,
70 		.height = 576,
71 		.frm_fmt = 1,
72 		.ycmux_mode = 0,
73 		.eav2sav = 144-8,
74 		.sav2eav = 720,
75 		.l1 = 1,
76 		.l3 = 45,
77 		.l5 = 621,
78 		.vsize = 625,
79 		.capture_format = 0,
80 		.vbi_supported = 0,
81 		.hd_sd = 1,
82 		.dv_preset = V4L2_DV_576P50,
83 	},
84 	{
85 		.name = "720p50",
86 		.width = 1280,
87 		.height = 720,
88 		.frm_fmt = 1,
89 		.ycmux_mode = 0,
90 		.eav2sav = 700-8,
91 		.sav2eav = 1280,
92 		.l1 = 1,
93 		.l3 = 26,
94 		.l5 = 746,
95 		.vsize = 750,
96 		.capture_format = 0,
97 		.vbi_supported = 0,
98 		.hd_sd = 1,
99 		.dv_preset = V4L2_DV_720P50,
100 	},
101 	{
102 		.name = "720p60",
103 		.width = 1280,
104 		.height = 720,
105 		.frm_fmt = 1,
106 		.ycmux_mode = 0,
107 		.eav2sav = 370 - 8,
108 		.sav2eav = 1280,
109 		.l1 = 1,
110 		.l3 = 26,
111 		.l5 = 746,
112 		.vsize = 750,
113 		.capture_format = 0,
114 		.vbi_supported = 0,
115 		.hd_sd = 1,
116 		.dv_preset = V4L2_DV_720P60,
117 	},
118 	{
119 		.name = "1080I50",
120 		.width = 1920,
121 		.height = 1080,
122 		.frm_fmt = 0,
123 		.ycmux_mode = 0,
124 		.eav2sav = 720 - 8,
125 		.sav2eav = 1920,
126 		.l1 = 1,
127 		.l3 = 21,
128 		.l5 = 561,
129 		.l7 = 563,
130 		.l9 = 584,
131 		.l11 = 1124,
132 		.vsize = 1125,
133 		.capture_format = 0,
134 		.vbi_supported = 0,
135 		.hd_sd = 1,
136 		.dv_preset = V4L2_DV_1080I50,
137 	},
138 	{
139 		.name = "1080I60",
140 		.width = 1920,
141 		.height = 1080,
142 		.frm_fmt = 0,
143 		.ycmux_mode = 0,
144 		.eav2sav = 280 - 8,
145 		.sav2eav = 1920,
146 		.l1 = 1,
147 		.l3 = 21,
148 		.l5 = 561,
149 		.l7 = 563,
150 		.l9 = 584,
151 		.l11 = 1124,
152 		.vsize = 1125,
153 		.capture_format = 0,
154 		.vbi_supported = 0,
155 		.hd_sd = 1,
156 		.dv_preset = V4L2_DV_1080I60,
157 	},
158 	{
159 		.name = "1080p60",
160 		.width = 1920,
161 		.height = 1080,
162 		.frm_fmt = 1,
163 		.ycmux_mode = 0,
164 		.eav2sav = 280 - 8,
165 		.sav2eav = 1920,
166 		.l1 = 1,
167 		.l3 = 42,
168 		.l5 = 1122,
169 		.vsize = 1125,
170 		.capture_format = 0,
171 		.vbi_supported = 0,
172 		.hd_sd = 1,
173 		.dv_preset = V4L2_DV_1080P60,
174 	},
175 
176 	/* SDTV formats */
177 	{
178 		.name = "NTSC_M",
179 		.width = 720,
180 		.height = 480,
181 		.frm_fmt = 0,
182 		.ycmux_mode = 1,
183 		.eav2sav = 268,
184 		.sav2eav = 1440,
185 		.l1 = 1,
186 		.l3 = 23,
187 		.l5 = 263,
188 		.l7 = 266,
189 		.l9 = 286,
190 		.l11 = 525,
191 		.vsize = 525,
192 		.capture_format = 0,
193 		.vbi_supported = 1,
194 		.hd_sd = 0,
195 		.stdid = V4L2_STD_525_60,
196 	},
197 	{
198 		.name = "PAL_BDGHIK",
199 		.width = 720,
200 		.height = 576,
201 		.frm_fmt = 0,
202 		.ycmux_mode = 1,
203 		.eav2sav = 280,
204 		.sav2eav = 1440,
205 		.l1 = 1,
206 		.l3 = 23,
207 		.l5 = 311,
208 		.l7 = 313,
209 		.l9 = 336,
210 		.l11 = 624,
211 		.vsize = 625,
212 		.capture_format = 0,
213 		.vbi_supported = 1,
214 		.hd_sd = 0,
215 		.stdid = V4L2_STD_625_50,
216 	},
217 };
218 
219 const unsigned int vpif_ch_params_count = ARRAY_SIZE(ch_params);
220 
vpif_wr_bit(u32 reg,u32 bit,u32 val)221 static inline void vpif_wr_bit(u32 reg, u32 bit, u32 val)
222 {
223 	if (val)
224 		vpif_set_bit(reg, bit);
225 	else
226 		vpif_clr_bit(reg, bit);
227 }
228 
229 /* This structure is used to keep track of VPIF size register's offsets */
230 struct vpif_registers {
231 	u32 h_cfg, v_cfg_00, v_cfg_01, v_cfg_02, v_cfg, ch_ctrl;
232 	u32 line_offset, vanc0_strt, vanc0_size, vanc1_strt;
233 	u32 vanc1_size, width_mask, len_mask;
234 	u8 max_modes;
235 };
236 
237 static const struct vpif_registers vpifregs[VPIF_NUM_CHANNELS] = {
238 	/* Channel0 */
239 	{
240 		VPIF_CH0_H_CFG, VPIF_CH0_V_CFG_00, VPIF_CH0_V_CFG_01,
241 		VPIF_CH0_V_CFG_02, VPIF_CH0_V_CFG_03, VPIF_CH0_CTRL,
242 		VPIF_CH0_IMG_ADD_OFST, 0, 0, 0, 0, 0x1FFF, 0xFFF,
243 		VPIF_CH0_MAX_MODES,
244 	},
245 	/* Channel1 */
246 	{
247 		VPIF_CH1_H_CFG, VPIF_CH1_V_CFG_00, VPIF_CH1_V_CFG_01,
248 		VPIF_CH1_V_CFG_02, VPIF_CH1_V_CFG_03, VPIF_CH1_CTRL,
249 		VPIF_CH1_IMG_ADD_OFST, 0, 0, 0, 0, 0x1FFF, 0xFFF,
250 		VPIF_CH1_MAX_MODES,
251 	},
252 	/* Channel2 */
253 	{
254 		VPIF_CH2_H_CFG, VPIF_CH2_V_CFG_00, VPIF_CH2_V_CFG_01,
255 		VPIF_CH2_V_CFG_02, VPIF_CH2_V_CFG_03, VPIF_CH2_CTRL,
256 		VPIF_CH2_IMG_ADD_OFST, VPIF_CH2_VANC0_STRT, VPIF_CH2_VANC0_SIZE,
257 		VPIF_CH2_VANC1_STRT, VPIF_CH2_VANC1_SIZE, 0x7FF, 0x7FF,
258 		VPIF_CH2_MAX_MODES
259 	},
260 	/* Channel3 */
261 	{
262 		VPIF_CH3_H_CFG, VPIF_CH3_V_CFG_00, VPIF_CH3_V_CFG_01,
263 		VPIF_CH3_V_CFG_02, VPIF_CH3_V_CFG_03, VPIF_CH3_CTRL,
264 		VPIF_CH3_IMG_ADD_OFST, VPIF_CH3_VANC0_STRT, VPIF_CH3_VANC0_SIZE,
265 		VPIF_CH3_VANC1_STRT, VPIF_CH3_VANC1_SIZE, 0x7FF, 0x7FF,
266 		VPIF_CH3_MAX_MODES
267 	},
268 };
269 
270 /* vpif_set_mode_info:
271  * This function is used to set horizontal and vertical config parameters
272  * As per the standard in the channel, configure the values of L1, L3,
273  * L5, L7  L9, L11 in VPIF Register , also write width and height
274  */
vpif_set_mode_info(const struct vpif_channel_config_params * config,u8 channel_id,u8 config_channel_id)275 static void vpif_set_mode_info(const struct vpif_channel_config_params *config,
276 				u8 channel_id, u8 config_channel_id)
277 {
278 	u32 value;
279 
280 	value = (config->eav2sav & vpifregs[config_channel_id].width_mask);
281 	value <<= VPIF_CH_LEN_SHIFT;
282 	value |= (config->sav2eav & vpifregs[config_channel_id].width_mask);
283 	regw(value, vpifregs[channel_id].h_cfg);
284 
285 	value = (config->l1 & vpifregs[config_channel_id].len_mask);
286 	value <<= VPIF_CH_LEN_SHIFT;
287 	value |= (config->l3 & vpifregs[config_channel_id].len_mask);
288 	regw(value, vpifregs[channel_id].v_cfg_00);
289 
290 	value = (config->l5 & vpifregs[config_channel_id].len_mask);
291 	value <<= VPIF_CH_LEN_SHIFT;
292 	value |= (config->l7 & vpifregs[config_channel_id].len_mask);
293 	regw(value, vpifregs[channel_id].v_cfg_01);
294 
295 	value = (config->l9 & vpifregs[config_channel_id].len_mask);
296 	value <<= VPIF_CH_LEN_SHIFT;
297 	value |= (config->l11 & vpifregs[config_channel_id].len_mask);
298 	regw(value, vpifregs[channel_id].v_cfg_02);
299 
300 	value = (config->vsize & vpifregs[config_channel_id].len_mask);
301 	regw(value, vpifregs[channel_id].v_cfg);
302 }
303 
304 /* config_vpif_params
305  * Function to set the parameters of a channel
306  * Mainly modifies the channel ciontrol register
307  * It sets frame format, yc mux mode
308  */
config_vpif_params(struct vpif_params * vpifparams,u8 channel_id,u8 found)309 static void config_vpif_params(struct vpif_params *vpifparams,
310 				u8 channel_id, u8 found)
311 {
312 	const struct vpif_channel_config_params *config = &vpifparams->std_info;
313 	u32 value, ch_nip, reg;
314 	u8 start, end;
315 	int i;
316 
317 	start = channel_id;
318 	end = channel_id + found;
319 
320 	for (i = start; i < end; i++) {
321 		reg = vpifregs[i].ch_ctrl;
322 		if (channel_id < 2)
323 			ch_nip = VPIF_CAPTURE_CH_NIP;
324 		else
325 			ch_nip = VPIF_DISPLAY_CH_NIP;
326 
327 		vpif_wr_bit(reg, ch_nip, config->frm_fmt);
328 		vpif_wr_bit(reg, VPIF_CH_YC_MUX_BIT, config->ycmux_mode);
329 		vpif_wr_bit(reg, VPIF_CH_INPUT_FIELD_FRAME_BIT,
330 					vpifparams->video_params.storage_mode);
331 
332 		/* Set raster scanning SDR Format */
333 		vpif_clr_bit(reg, VPIF_CH_SDR_FMT_BIT);
334 		vpif_wr_bit(reg, VPIF_CH_DATA_MODE_BIT, config->capture_format);
335 
336 		if (channel_id > 1)	/* Set the Pixel enable bit */
337 			vpif_set_bit(reg, VPIF_DISPLAY_PIX_EN_BIT);
338 		else if (config->capture_format) {
339 			/* Set the polarity of various pins */
340 			vpif_wr_bit(reg, VPIF_CH_FID_POLARITY_BIT,
341 					vpifparams->iface.fid_pol);
342 			vpif_wr_bit(reg, VPIF_CH_V_VALID_POLARITY_BIT,
343 					vpifparams->iface.vd_pol);
344 			vpif_wr_bit(reg, VPIF_CH_H_VALID_POLARITY_BIT,
345 					vpifparams->iface.hd_pol);
346 
347 			value = regr(reg);
348 			/* Set data width */
349 			value &= ((~(unsigned int)(0x3)) <<
350 					VPIF_CH_DATA_WIDTH_BIT);
351 			value |= ((vpifparams->params.data_sz) <<
352 						     VPIF_CH_DATA_WIDTH_BIT);
353 			regw(value, reg);
354 		}
355 
356 		/* Write the pitch in the driver */
357 		regw((vpifparams->video_params.hpitch),
358 						vpifregs[i].line_offset);
359 	}
360 }
361 
362 /* vpif_set_video_params
363  * This function is used to set video parameters in VPIF register
364  */
vpif_set_video_params(struct vpif_params * vpifparams,u8 channel_id)365 int vpif_set_video_params(struct vpif_params *vpifparams, u8 channel_id)
366 {
367 	const struct vpif_channel_config_params *config = &vpifparams->std_info;
368 	int found = 1;
369 
370 	vpif_set_mode_info(config, channel_id, channel_id);
371 	if (!config->ycmux_mode) {
372 		/* YC are on separate channels (HDTV formats) */
373 		vpif_set_mode_info(config, channel_id + 1, channel_id);
374 		found = 2;
375 	}
376 
377 	config_vpif_params(vpifparams, channel_id, found);
378 
379 	regw(0x80, VPIF_REQ_SIZE);
380 	regw(0x01, VPIF_EMULATION_CTRL);
381 
382 	return found;
383 }
384 EXPORT_SYMBOL(vpif_set_video_params);
385 
vpif_set_vbi_display_params(struct vpif_vbi_params * vbiparams,u8 channel_id)386 void vpif_set_vbi_display_params(struct vpif_vbi_params *vbiparams,
387 				u8 channel_id)
388 {
389 	u32 value;
390 
391 	value = 0x3F8 & (vbiparams->hstart0);
392 	value |= 0x3FFFFFF & ((vbiparams->vstart0) << 16);
393 	regw(value, vpifregs[channel_id].vanc0_strt);
394 
395 	value = 0x3F8 & (vbiparams->hstart1);
396 	value |= 0x3FFFFFF & ((vbiparams->vstart1) << 16);
397 	regw(value, vpifregs[channel_id].vanc1_strt);
398 
399 	value = 0x3F8 & (vbiparams->hsize0);
400 	value |= 0x3FFFFFF & ((vbiparams->vsize0) << 16);
401 	regw(value, vpifregs[channel_id].vanc0_size);
402 
403 	value = 0x3F8 & (vbiparams->hsize1);
404 	value |= 0x3FFFFFF & ((vbiparams->vsize1) << 16);
405 	regw(value, vpifregs[channel_id].vanc1_size);
406 
407 }
408 EXPORT_SYMBOL(vpif_set_vbi_display_params);
409 
vpif_channel_getfid(u8 channel_id)410 int vpif_channel_getfid(u8 channel_id)
411 {
412 	return (regr(vpifregs[channel_id].ch_ctrl) & VPIF_CH_FID_MASK)
413 					>> VPIF_CH_FID_SHIFT;
414 }
415 EXPORT_SYMBOL(vpif_channel_getfid);
416 
vpif_probe(struct platform_device * pdev)417 static int __init vpif_probe(struct platform_device *pdev)
418 {
419 	int status = 0;
420 
421 	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
422 	if (!res)
423 		return -ENOENT;
424 
425 	res_len = resource_size(res);
426 
427 	res = request_mem_region(res->start, res_len, res->name);
428 	if (!res)
429 		return -EBUSY;
430 
431 	vpif_base = ioremap(res->start, res_len);
432 	if (!vpif_base) {
433 		status = -EBUSY;
434 		goto fail;
435 	}
436 
437 	spin_lock_init(&vpif_lock);
438 	dev_info(&pdev->dev, "vpif probe success\n");
439 	return 0;
440 
441 fail:
442 	release_mem_region(res->start, res_len);
443 	return status;
444 }
445 
vpif_remove(struct platform_device * pdev)446 static int __devexit vpif_remove(struct platform_device *pdev)
447 {
448 	iounmap(vpif_base);
449 	release_mem_region(res->start, res_len);
450 	return 0;
451 }
452 
453 static struct platform_driver vpif_driver = {
454 	.driver = {
455 		.name	= "vpif",
456 		.owner = THIS_MODULE,
457 	},
458 	.remove = __devexit_p(vpif_remove),
459 	.probe = vpif_probe,
460 };
461 
vpif_exit(void)462 static void vpif_exit(void)
463 {
464 	platform_driver_unregister(&vpif_driver);
465 }
466 
vpif_init(void)467 static int __init vpif_init(void)
468 {
469 	return platform_driver_register(&vpif_driver);
470 }
471 subsys_initcall(vpif_init);
472 module_exit(vpif_exit);
473 
474